PHPUnit ことはじめ (インストール＆テストスイート構築)

## 動作確認環境

今回の環境: macOS Sierra + PHP 7.1.1 + Composer 1.3.1 + PHPUnit 5.7.8

macOS に Homebrew で PHP と Composer をインストールしてある状態。

```
$ php --version
PHP 7.1.1 (cli) (built: Jan 21 2017 13:36:56) ( NTS )
Copyright (c) 1997-2017 The PHP Group
Zend Engine v3.1.0, Copyright (c) 1998-2017 Zend Technologies

$ composer --version
Composer version 1.3.1 2017-01-07 18:08:51
```

## Composer で PHPUnit をインストールする

composer.json ファイルを用意して、

```
{
    "require-dev": {
        "phpunit/phpunit": "5.7.*"
    }
}
```

composer install コマンドで PHPUnit をインストールする。

```
$ composer install
```

PHPUnit のコマンドが vendor/bin/phpunit にインストールされる。
バージョンを確認する。

```
$ ./vendor/bin/phpunit --version
PHPUnit 5.7.8 by Sebastian Bergmann and contributors.
```

## シンプルで小さいテストを実行してみる

src/Message.php に Message クラスを書く。

```
<?php

class Message
{

    private $message;

    public function __construct(string $message)
    {
        $this->message = $message;
    }

    public function get(): string
    {
        return $this->message;
    }
}
```

tests/MessageTest.php にテストケースクラスを書く。

```
<?php

use PHPUnit\Framework\TestCase;

class MessageTest extends TestCase
{
    public function testGet(): void
    {
        $message = new Message('hello, world');
        $this->assertEquals('hello, world', $message->get());
    }
}
```

PHPUnit でテストを実行する。

```
$ ./vendor/bin/phpunit --bootstrap src/Message.php tests/MessageTest.php 
PHPUnit 5.7.8 by Sebastian Bergmann and contributors.

.                                                                   1 / 1 (100%)

Time: 35 ms, Memory: 4.00MB

OK (1 test, 1 assertion)
```

## もうちょっと大きいプログラムのテストを実行する

クラスファイルが増えてもテストできるようなディレクトリ・ファイル構成をつくる。

```
.
├── composer.json
├── phpunit.xml
├── src
│   └── Message.php
└── tests
    ├── MessageTest.php
    └── bootstrap.php
```

src/Message.php の Message クラスを少し書き直して、MyApp という名前空間を指定する。

```
<?php

namespace MyApp;

class Message
{
    private $text;

    public function __construct(string $text)
    {
        $this->text = $text;
    }

    public function getMessage(): string
    {
        return $this->text;
    }

    public function setMessage($text): void
    {
        $this->text = $text;
    }
}
```

tests/MessageTest.php のテストケースクラスを書き直す。

```
<?php

use PHPUnit\Framework\TestCase;
use MyApp\Message;

class MessageTest extends TestCase
{
    private $message;

    // 各テストメソッドが実行される前に呼び出されるメソッド
    protected function setUp()
    {
        $this->message = new Message('hello, world');
    }

    // テストメソッド: getMessage をテストする
    public function testGetMessage(): void
    {
        $this->assertEquals('hello, world', $this->message->getMessage());
    }

    // テストメソッド: setMessage をテストする
    public function testSetMessage(): void
    {
        $this->message->setMessage('good-bye, world');
        $this->assertEquals('good-bye, world', $this->message->getMessage());
    }

    // 各テストメソッドが実行された後に呼び出されるメソッド
    protected function tearDown()
    {
        // do nothing
    }

    // テストケースクラスの最初のテストメソッドの実行前に呼び出される
    public static function setUpBeforeClass()
    {
        fwrite(STDOUT, PHP_EOL . __METHOD__ . PHP_EOL); // DEBUG
    }

    // テストケースクラスの最後のテストメソッドの実行後に呼び出される
    public static function tearDownAfterClass()
    {
        fwrite(STDOUT, PHP_EOL . __METHOD__ . PHP_EOL); // DEBUG
    }
}
```

テスト実行時に使う tests/bootstrap.php を追加する。
bootstrap.php の中では vendor/autoload.php を読み込むようにしておく。

```
<?php
require __DIR__ . '/../vendor/autoload.php';
```

composer.json に autoload の項目を追加する。

```
{
    "autoload": {
        "psr-4": {
            "MyApp\\": "src/"
        }
    },

    "require-dev": {
        "phpunit/phpunit": "5.7.*"
    }
}
```

composer dump-autoload を実行して、MyApp 名前空間を vendor/autoload.php に反映させる。

```
$ composer dump-autoload
Generating autoload files
```

XML 設定ファイル phpunit.xml を追加する。

```
<phpunit bootstrap="tests/bootstrap.php">
  <testsuites>
    <testsuite name="hello-test">
      <directory>tests</directory>
    </testsuite>
  </testsuites>
</phpunit>
```

PHPUnit を実行してテストを実施する。

```
$ ./vendor/bin/phpunit 
PHPUnit 5.7.9 by Sebastian Bergmann and contributors.


MessageTest::setUpBeforeClass
..                                                                  2 / 2 (100%)
MessageTest::tearDownAfterClass


Time: 47 ms, Memory: 4.00MB

OK (2 tests, 2 assertions)
```

## 参考資料

- PHPUnit マニュアル – 第1章 PHPUnit のインストール https://phpunit.de/manual/current/ja/installation.html
- Getting Started with PHPUnit – The PHP Testing Framework https://phpunit.de/getting-started.html