データプロバイダで同じテストを複数の入力に回す

データプロバイダとは、入力と期待値のセットを別メソッドで供給し、一本のテストに次々流し込むPHPUnitの仕組みです。同じ検証ロジックを値だけ変えて繰り返す手間を省けます。

同じテストをコピペで増やさない

境界値をいくつも確かめたいとき、テストメソッドを丸ごとコピペして値だけ差し替える、というのをやりがちです。ただこれはケースが増えるほど保守が辛くなります。データプロバイダは「入力と期待値のセット」を別メソッドで供給して、一本のテストに次々流し込む仕組みですね。テスト本体はひとつで済みます。

use PHPUnit\Framework\Attributes\DataProvider;

final class TaxTest extends TestCase
{
    #[DataProvider('priceProvider')]
    public function test_税込計算(int $price, int $expected): void
    {
        $this->assertSame($expected, withTax($price));
    }
}

プロバイダはstaticでケースを返す

プロバイダメソッドは static にして、各ケースを配列で返します。返す配列の中身が、そのままテストメソッドの引数の順に渡ります。キーを付けておくと、失敗時にどのケースが落ちたかが名前で表示されて追いやすくなるので、私は必ず名前を付けています。

public static function priceProvider(): array
{
    return [
        '通常価格' => [100, 110],
        'ゼロ円'   => [0, 0],
        '端数あり' => [105, 115], // 丸めの確認
    ];
}

「端数あり」のように名前で意図を書いておくと、テストコードそのものが仕様の一覧みたいになるのが気に入っています。

ジェネレータで返す手もある

ケースが多いときや動的に組み立てたいときは、配列ではなく yield で返すこともできます。書き味が縦に並んで見やすいので、私はケースが増えたらこちらに寄せることが多いですね。

public static function priceProvider(): Generator
{
    yield '通常価格' => [100, 110];
    yield 'ゼロ円'   => [0, 0];
    yield '端数あり' => [105, 115];
}

まとめ

入力だけが違って検証ロジックは同じ、というテストはデータプロバイダの出番だと思います。ケースを足すのがプロバイダに一行加えるだけになるので、境界値を気軽に増やせるのが大きいですね。ケースに名前を付けておくと失敗時の追跡がぐっと楽になるので、その一手間はかけておきたいところです。

よくある質問

Q. プロバイダメソッドは static でないとだめですか?
A. はい、データプロバイダは static メソッドにして、各ケースを配列や yield で返します。返した値がそのままテストメソッドの引数の順に渡ります。

Q. どのケースで落ちたか分かりやすくするには?
A. 返す配列にケース名のキーを付けておくと、失敗時にその名前が表示されて追いやすくなります。仕様の一覧にもなるので付けておくのがおすすめです。

類似投稿

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です