PHPUnitを使ってみる

# What's？

PHPUnitを始めてみたい、という記事です。

こちらを読みながら、進めていってみます。

https://phpunit.readthedocs.io/ja/latest/index.html

# 環境

今回の環境は、こちら。

```shell
$ php --version
PHP 7.4.26 (cli) (built: Nov 18 2021 16:12:41) ( NTS )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies


$ composer --version
Composer version 2.1.12 2021-11-09 16:02:04
```


# プロジェクトを作成する

まずは、プロジェクトを作成します。

```shell
$ composer init
```

こんな情報で作成しました。

```shell
Package name (<vendor>/<name>) [root/app]: charon/phpunit-getting-started                                                                                                          
Description []:                                                                                                                                                                    
Author [, n to skip]: n                                                                                                                                                            
Minimum Stability []:                                                                                                                                                              
Package Type (e.g. library, project, metapackage, composer-plugin) []: project                                                                                                     
License []:                                                                                                                                                                        
                                                                                                                                                                                   
Define your dependencies.                                                                                                                                                          
                                                                                                                                                                                   
Would you like to define your dependencies (require) interactively [yes]? no                                                                                                       
Would you like to define your dev dependencies (require-dev) interactively [yes]? no                                                                                               
Add PSR-4 autoload mapping? Maps namespace "Charon\PhpunitGettingStarted" to the entered relative path. [src/, n to skip]:
```

PHPのバージョンは、使っているものに合わせておきます。

```shell
$ composer config platform.php 7.4.26
```

続いて、PHPUnitのインストール。

https://phpunit.readthedocs.io/ja/latest/installation.html

```shell
$ composer require --dev phpunit/phpunit
```

`composer.json`に追加された依存関係。

```json
    "require-dev": {
        "phpunit/phpunit": "^9.5"
    }
```

実際のバージョンは、こちら。

```shell
$ vendor/phpunit/phpunit/phpunit --version
PHPUnit 9.5.10 by Sebastian Bergmann and contributors.
```

`composer init`時にソースコードの配置先は`src`になっているのですが、テストコードの配置先はどうしようかなと。

こちらを見て

https://phpunit.readthedocs.io/ja/latest/organizing-tests.html

`tests`ディレクトリにすることにしました。

```shell
$ mkdir tests
```

これで、プロジェクトの準備は完了です。

# ソースコード、テストコードを書く

では、プログラムを書いていきます。

最初は、テスト対象のコードを書きましょう。

```php:src/Calc.php
<?php

namespace Charon\PhpunitGettingStarted;

class Calc
{
    public function add($a, $b) {
        return $a + $b;
    }

    public function minus($a, $b) {
        return $a - $b;
    }
}
```

続いて、テストコード。

こちらを見ながら書いていきます。

https://phpunit.readthedocs.io/ja/latest/writing-tests-for-phpunit.html

```php:tests/CalcTest.php
<?php

namespace Charon\PhpunitGettingStarted;

use PHPUnit\Framework\TestCase;

class CalcTest extends TestCase
{
    public function testAdd()
    {
        $calc = new Calc();
        $this->assertSame(3, $calc->add(1, 2));
    }

    public function testMinus()
    {
        $calc = new Calc();
        $this->assertSame(1, $calc->minus(3, 2));
    }
}
```

ポイントは、

- クラス名の末尾は`Test`とする
- `PHPUnit\Framework\TestCase`クラスを継承する
- テストメソッドは、`test`で始める

あたりですね。

# PHPUnitを実行する

では、作成したテストを実行します。

https://phpunit.readthedocs.io/ja/latest/textui.html

テストディレクトリを指定して、実行。

```shell
$ vendor/phpunit/phpunit/phpunit tests
```

OKでした。

```shell
PHPUnit 9.5.10 by Sebastian Bergmann and contributors.

..                                                                  2 / 2 (100%)

Time: 00:00.006, Memory: 4.00 MB

OK (2 tests, 2 assertions)
```

失敗するケースも試してみましょう。

`minus`のテストケースに間違いを仕込んでみます。

```php
    public function testMinus()
    {
        $calc = new Calc();
        $this->assertSame(2, $calc->minus(3, 2));
    }
```

再度テストを実行。

```shell
$ vendor/phpunit/phpunit/phpunit tests
PHPUnit 9.5.10 by Sebastian Bergmann and contributors.

.F                                                                  2 / 2 (100%)

Time: 00:00.008, Memory: 4.00 MB

There was 1 failure:

1) Charon\PhpunitGettingStarted\CalcTest::testMinus
Failed asserting that 1 is identical to 2.

/app/tests/CalcTest.php:18

FAILURES!
Tests: 2, Assertions: 2, Failures: 1.
```

対象のテストの失敗が確認できました。

# autoload

ところで、テストコードで`vendor/autoload.php`を`require_once`していないのに、PHPUnitへの依存関係が解決できるのがよくわからなかったのですが。

PHPUnitが見ているみたいですね。

たとえば、`vendor/autoload.php`をリネームしてみると

```shell
$ mv vendor/autoload.php vendor/autoload.php_
```

PHPUnitが実行できなくなります。

```shell
$ vendor/phpunit/phpunit/phpunit tests
You need to set up the project dependencies using Composer:

    composer install

You can learn all about Composer on https://getcomposer.org/.
```

Composerを使っていることを期待しているみたいですね。このあたりのようです。

https://github.com/sebastianbergmann/phpunit/blob/9.5.10/phpunit#L61-L80