データプロバイダで同じテストを複数の入力に回す
データプロバイダとは、入力と期待値のセットを別メソッドで供給し、一本のテストに次々流し込む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. 返す配列にケース名のキーを付けておくと、失敗時にその名前が表示されて追いやすくなります。仕様の一覧にもなるので付けておくのがおすすめです。