PHPUnitの公式ドキュメントを全部読んだので大事なところをまとめてみた

# はじめに

はじめまして株式会社ナイトレイの渡辺です。

現在私が関わっているプロダクトでPHPのユニットテストを導入した際、PHPUnitを利用するにあたって公式ドキュメントを一通り読んだので、この記事では個人的に重要な箇所を備忘録としてまとめます。




💡 本記事で記載されている内容はこちらのドキュメントから引用させていただいております

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


## 対象読者

- 少しPHPUnitを使ったことがある
- PHPUnitをもっと上手く使いたい

## 環境

PHPUnit 9.5.20

# 内容

## ****PHPUnit 用のテストの書き方****

この章では、PHPUnit を使ったテストを書く際の基本的な決まり事や手順を紹介しています。

最低限、PHPUnitでテストを書く上で必要な情報なので一通り目を通すことを推奨します。

[https://phpunit.readthedocs.io/ja/latest/writing-tests-for-phpunit.html](https://phpunit.readthedocs.io/ja/latest/writing-tests-for-phpunit.html)

## フィクスチャ

### テンプレートメソッド

テンプレートメソッド `setUp()` および `tearDown()` は、テストケースクラスのテストメソッドごとに (そして最初にインスタンスを作成したときに) 一度ずつ実行されます。

また、テンプレートメソッド `setUpBeforeClass()`および `tearDownAfterClass()`が存在します。 これらはそれぞれ、テストケースクラスの最初のテストメソッドの実行前と テストケースクラスの最後のテストの実行後にコールされます。

### アンチパターン

Example 4.3 テストスイートの複数テスト間でのフィクスチャの共有

```php
<?php declare(strict_types=1);
use PHPUnit\Framework\TestCase;

final class DatabaseTest extends TestCase
{
    private static $dbh;

    public static function setUpBeforeClass(): void
    {
        self::$dbh = new PDO('sqlite::memory:');
    }

    public static function tearDownAfterClass(): void
    {
        self::$dbh = null;
    }
}
```

<aside>
🚫 複数テスト間でのフィクスチャの共有してしまっており、各オブジェクトが疎結合になっていない。

</aside>

### tearDown()の使い所

`tearDown()`を実装する必要があるのは`setUp()`で外部リソース (ファイルやソケットなど) を割り当てた場合のみです。もし `setUp()`で単に PHP オブジェクトを作成しただけの場合は、 一般には `tearDown()`は必要ありません。

## phpunit.xmlについて

### beStrictAboutTestsThatDoNotTestAnything="false”

PHPUnit はデフォルトで、何も確かめていないテストを検出します。 このチェックを無効にするには、コマンドラインオプション `--dont-report-useless-tests` を使うか、あるいは PHPUnit の XML 設定ファイルで `beStrictAboutTestsThatDoNotTestAnything="false"` を設定します。

何もアサーションを実行していないテストは、このチェックを有効にしておくと、 危険であるとマークされます。モックオブジェクトでの例外や、 @expectedException などのアノテーションは、アサーションとみなします。

### beStrictAboutOutputDuringTests="true”

PHPUnit は、テストの最中の出力を検出することができます。 このチェックを有効にするには、コマンドラインオプション `--disallow-test-output` を使うか、あるいは PHPUnit の XML 設定ファイルで `beStrictAboutOutputDuringTests="true"` を設定します。

テストコードあるいは被テストコードの中で、print などで何かを出力している場合に、 このチェックを有効にしておくと、危険であるとマークされます。

### ****XML 設定ファイルを用いたテストスイートの構成**

PHPUnit の XML 設定ファイルを使ってテストスイートを構成することができます。
[Example 5.1](https://phpunit.readthedocs.io/ja/latest/organizing-tests.html#organizing-tests-xml-configuration-examples-phpunit-xml) で一番シンプルな`phpunit.xml`ファイルを示します。これは、`tests` ディレクトリを再帰的に探索して `*Test.php` というファイルにある `*Test` クラスをすべて追加する設定です。

Example 5.1 XML 設定ファイルを用いたテストスイートの構成

```xml
<phpunit bootstrap="src/autoload.php">
  <testsuites>
    <testsuite name="money">
      <directory>tests</directory>
    </testsuite>
  </testsuites>
</phpunit>
```

特定のテストスイートを実行したい場合は、`--testsuite` オプションを利用します。

```
$ phpunit --bootstrap src/autoload.php --testsuite money
PHPUnit latest.0 by Sebastian Bergmann and contributors.

..
Time: 167 ms, Memory: 3.00Mb

OK (2 test, 2 assertions)

```

- `-configuration` が設定 *されていない* 場合は、現在の作業ディレクトリから `phpunit.xml` あるいは `phpunit.xml.dist` を (この順に) 探し、 見つかった場合はそれを自動的に読み込みます。

また以下のように、テストの実行順序を XML 設定ファイルで明示的に指定することもできます。

Example 5.2 XML 設定ファイルを用いたテストスイートの構成

```xml
<phpunit bootstrap="src/autoload.php">
  <testsuites>
    <testsuite name="money">
      <file>tests/IntlFormatterTest.php</file>
      <file>tests/MoneyTest.php</file>
      <file>tests/CurrencyTest.php</file>
    </testsuite>
  </testsuites>
</phpunit>
```

## 不完全なテスト・テストの省略

### テストに未完成の印をつける

[Example 7.1](https://phpunit.readthedocs.io/ja/latest/incomplete-and-skipped-tests.html#incomplete-and-skipped-tests-incomplete-tests-examples-sampletest-php) では `SampleTest` というテストケースクラスを定義しています。 `markTestIncomplete()` をテストメソッド内でコールすることで、 このメソッドがまだ完成していないことをはっきりさせます。

Example 7.1 テストに未完成の印をつける

```php
use PHPUnit\Framework\TestCase;

final class SampleTest extends TestCase
{
    public function testSomething(): void
    {
        // オプション: お望みなら、ここで何かのテストをしてください。
        $this->assertTrue(true, 'これは動いているはずです。');

        // ここで処理を止め、テストが未完成であるという印をつけます。
        $this->markTestIncomplete(
          'このテストは、まだ実装されていません。'
        );
    }
}
```

未完成のテストは、PHPUnit のコマンドライン版テストランナーでは以下のように `I`
 で表されます。

```bash
$ phpunit --verbose SampleTest
PHPUnit latest.0 by Sebastian Bergmann and contributors.

I

Time: 0 seconds, Memory: 3.95Mb

There was 1 incomplete test:

1) SampleTest::testSomething
このテストは、まだ実装されていません。

/home/sb/SampleTest.php:12
OK, but incomplete or skipped tests!
Tests: 1, Assertions: 1, Incomplete: 1.
```

## アサーション

### 利用可能なアサーションメソッドの一覧

この章では、利用可能なアサーションメソッドの一覧が記載されています。

実際にテストを書く中で、どのような時にどのアサーションを使えばいいのかを考えるタイミングがあります。その度にこの章を見返すことで最適なアサーションを選択できるようになります。

[https://phpunit.readthedocs.io/ja/latest/assertions.html](https://phpunit.readthedocs.io/ja/latest/assertions.html)

## アノテーション

### ****@testdox****

アジャイルドキュメントを生成する際に使う別の説明を指定します。

`@testdox` アノテーションは、クラスにもテストメソッドにも指定できます。

```php
<?php **declare**(strict_types=1);
**use** PHPUnit\Framework\TestCase;

*/**
	* @testdox A bank account
*/*
**final** **class** **BankAccountTest** **extends** TestCase
{
    */**     
			* @testdox has an initial balance of zero
		*/*
		**public** **function** balanceIsInitiallyZero(): void
    {
        $this->assertSame(0, $this->ba->getBalance());
    }
}
```

### ****@dataProvider****

テストメソッドには任意の引数を渡すことができます。 引数は、データプロバイダメソッド ([配列の配列を返すデータプロバイダの使用](https://phpunit.readthedocs.io/ja/latest/writing-tests-for-phpunit.html#writing-tests-for-phpunit-data-providers-examples-datatest-php) の `provider()`) から渡されます。 使用するデータプロバイダメソッドを指定するには `@dataProvider` アノテーションを使います。

詳細は [データプロバイダ](https://phpunit.readthedocs.io/ja/latest/writing-tests-for-phpunit.html#writing-tests-for-phpunit-data-providers) を参照ください。

### ****@before****

`@before` アノテーションを使うと、 テストケースクラス内の各テストメソッドを実行する前に呼ぶメソッドを指定できます。

```php
<?php declare(strict_types=1);
use PHPUnit\Framework\TestCase;

final class MyTest extends TestCase
{
    /**
     * @before
     */
    public function setupSomeFixtures(): void
    {
        // ...
    }

    /**
     * @before
     */
    public function setupSomeOtherFixtures(): void
    {
        // ...
    }
}
```

### ****@after****

`@after` アノテーションを使うと、 テストケースクラス内の各テストメソッドを実行した後に呼ぶメソッドを指定できます。

# 最後に
私たちの会社、ナイトレイでは一緒に自社開発のWebサービスを盛り上げてくれるエンジニアメンバーを募集しています！ 
基本的には直接ユーザーと接することのないポジションですが、セールス部門から
「顧客の声」を教えてもらったり、希望すればユーザーとのMTGに参加することも可能です。
モチベーションの高め方はあなた次第。

このような方は是非Wantedlyからお気軽にご連絡ください（もしくはこちらまで recruit@nightley.jp ）

 ✔︎ 自社Webサービスの開発で事業の発展に携わってみたい
 ✔︎ 自分が開発したサービスで地域活性化に貢献したい
 ✔︎ 位置情報ビッグデータに興味があり、新しい活用方法を提案したい
 ✔︎ 地理や地図が好きで仕事中も眺めていたい 

一つでも当てはまる方は是非こちらの記事をご覧ください 

 https://www.wantedly.com/projects/467606 

▼ナイトレイとは？

https://www.wantedly.com/companies/nightley


# 参考文献

[https://phpunit.readthedocs.io/ja/latest/](https://phpunit.readthedocs.io/ja/latest/)