🧪

PHPUnitのアノテーションについてまとめてみた

2023/01/31に公開

PHPUnitのアノテーションについてまとめてみた

はじめに

はじめまして、ポートで バックエンドエンジニア をしている @sawada です。
今回は、PHPUnitでテスト作成する際に便利なアノテーションについてまとめてみました。
ご参考になれば幸いです。

@dataProvier

@dataProviderを使用することで、テストメソッドに任意の引数を渡す事ができ、容易にテストケースを増やすことができます。

記法

@dataProvider <dataProviderのメソッド名>となります。

/**
 * @dataProvider fooDataProvider
 */
public function test_foo($num, $num2, $num3) {
    $result = foo($num, $num2);
    $this->assertEquals($result, $num3);
}
public function fooDataProvider() {
    return [
        [1,3,5],
        [2,4,6],
        [3,5,7],
    ];
}

テストデータは、ベタ書きでもいいですが、ループで網羅的に作成することも可能です。
また、dataProviderで返す配列のキーに名前を付けておくと、テストが落ちた時に理由がわかりやすくなります。

/**
 * @dataProvider 状態変化の確認DataProvider
 */
public function test_状態変化の確認($from, $to) {
    $result = $obj->changeState($from);
    $this->assertEquals($result, $to);
}
public function 状態変化の確認DataProvider() {
    $data = [];
    foreach(State::LIST1 as $fromK => $fromV) {
        foreach(State::LIST2 as $toK => $toV) {
            $data[$fromK.'のとき'.$toV.'となる'] = [
                'from' => $fromV,
                'to' => $toV,
            ];
        }
    }

    return $data;
}

@testWith

@testWith を使用することで、@dataProvider と同じような機能を簡易的に実装することが可能となります。

記法

データセットはJSONの配列形式で記述することとなります。

/**
 * @testWith [2]
 *           [3]
 *           [4]
 */
public function test_foo($num) {
    //...
}

連想配列を利用したい場合は、オブジェクトの配列形式で記述することとなります。

/**
 * @testWith [{"key": "hoo", "value": "bar"}]
 *           [{"key": "hoo2", "value": "bar2"}]
 */
public function test_bar(array $array) {
    //...
}

@group

@group により、テストをグループ化することができます。
外部ライブラリ等の挙動を確認する際に、学習用テストを記述している場合は、後々削除できるようにグループ化しておくといいでしょう。

記法

/**
 * @group learning
 */
public function test_ライブラリーの挙動の確認() {
    // ...
}

また、メソッドのみならず、クラスにも定義することが可能です。
その場合、そのクラスのメソッドがすべて同じ@groupアノテーションを持つこととなります。

テスト実行時にグループを指定したい場合は、コマンドのオプションとして指定するか、phpunit.xmlで指定することとなります。

# 指定のグループのみ実行
./vendor/bin/phpunit tests/ --group learn
# 指定のグループ以外実行
./vendor/bin/phpunit tests/ --exclude-group learn
<groups>
  <include>
    <group>name</group>
  </include>
  <exclude>
    <group>learn</group>
  </exclude>
</groups>

また、@groupアノテーションには、@large,@medium等のエイリアスも存在します。

@depends

@depends を利用することで、指定したテストメソッドの戻り値を受け取ることができ、テストの依存関係を表現することができます。
テスト対象のメソッドを呼び出す際の前提条件を表現する際に利用することが多いです。

記法

public function test_インスタンス生成時のstateはfooであることを確認する() {
    $foo = new Foo();
    $this->assertEquals('foo', $foo->state);

    return $foo;
}
/**
 * @depends test_インスタンス生成時はstateはnewであることを確認する
 */
public function test_changeメソッドによりstateがbarに変更されることを確認する($foo) {
    $foo->change();
    $this->assertEquals('bar', $foo->state);
}

しかし、注意点として、下記のように depends を複数つなげてしまうと、可読性が低下する可能性もあるので、注意が必要です。

public function test_foo() {
    // assert..
    return $foo;
}
/**
 * @depends test_foo
 */
public function test_bar($foo) {
    // assert..
    return $bar;
}
/**
 * @depends test_bar
 */
public function test_foobar($bar) {
    // ...
}

まとめ

PHPUnit アノテーションについてまとめました。
これらを利用すれば、少ない工数で多くのテストケースを作成することが可能となります。
これらを利用し、資産となるテストコードを書いていきたいですね。

参考

https://phpunit.readthedocs.io/ja/latest/annotations.html
https://gihyo.jp/dev/serial/01/savanna-letter/0001

Discussion