PHPUnitでパラメタライズドテストをやってみる


概要

チームのメンバーがPHPUnitでのパラメタライズドテストを、都度読み出す形で書いていました。
PHPUnitの機能を使えば、もっと可読性を上げられると思ったので、自己学習も兼ねてやり方をまとめてみます。

パラメタライズドテスト

パラメタライズドテストとは、 渡す引数が違うだけで同じメソッドを何度もテストするというテスト方法になります。
今回は下記のFizzBuzzを使って、説明していきます。

FizzBuzz
declare(strict_types=1);

class FizzBuzz
{
    public function toFizzBuzz(int $count)
    {
        $result = '';
        if ($count % 3 == 0) {
            $result .= 'Fizz';
        }
        if ($count % 5 == 0) {
            $result .= 'Buzz';
        }
        if (!($count % 3 == 0)
            && !($count % 5 == 0)
        ) {
            $result .= $count;
        }
        return $result;
    }
}

このプログラムでテストコードを書く場合、 $countには複数のパラメータでテストを行うと思います。

  • 3の倍数のとき
  • 5の倍数のとき
  • 3と5の倍数のとき
  • それ以外の数字のとき

これを愚直に実装しようとすると

class FizzbuzzTest extends TestCase
{
    /**
     * @test
     */
    public function toFizzBuzzTest()
    {
        $obj = new FizzBuzz();
        $res = $obj->toFizzBuzz(1);
        $this->assertEquals($res, 1);

        $res = $obj->toFizzBuzz(3);
        $this->assertEquals($res, 'Fizz');

        $res = $obj->toFizzBuzz(5);
        $this->assertEquals($res, 'Buzz');

        $res = $obj->toFizzBuzz(15);
        $this->assertEquals($res, 'FizzBuzz');
    }
}

こんな風に冗長的になってしまうかなと思います。
これをPHPUnitの機能を使って、可読性を上げてみます。
使うのは@dataProviderアノテーションです。
@dataProviderアノテーションを使うことで、下記のように配列でデータを渡すことが出来ます。

class FizzbuzzTest extends TestCase
{
    public function toFizzBuzzDataProvider()
    {
        return [
            'number 1' => [1, 1],
            'number 3' => [3, 'Fizz'],
            'number 5' => [5, 'Buzz'],
            'number 15' => [15, 'FizzBuzz'],
        ];
    }

    /**
     * @test
     * @dataProvider toFizzBuzzDataProvider
     */
    public function toFizzBuzzTest($param, $actual)
    {
        $obj = new FizzBuzz();
        $res = $obj->toFizzBuzz($param);
        $this->assertEquals($res, $actual);
    }
}

こうして書いた方がパラメータが増えた時にテストが見やすくなるかなと思います。

備考

@dataProviderで渡す配列に名前をつけておくと、どこで失敗したかわかりやすいです。

最後に

今回の例ですとそこまで便利には見えませんが、複数のパラメータを渡して、何千行とコードが膨れ上がる際には、特に有効なのかなと思います。

最後まで読んで頂きありがとうございました。

参考