😺

PHPUnitのDataProviderの使い方

に公開

はじめに

PHPUnitを学習する機会があったので、備忘録としてまとめておく記事です。
PHPUnitのインストールや詳細な使い方については、こちらの記事を参考にしていただければと思います。

この記事で学べること

データプロバイダーを使用して、1つのメソッドを複数のデータセットでテストする方法がわかります。

動作環境

  • OS:macOS Sequoia 15.1.1
  • PHP:8.4.4
  • PHPUnit:12.1.4
  • Composer:2.5.1

DataProvidersを使用しない場合

引数の値を足し算した結果を返すクラスをテストします。

src/Calculator.php
<?php
namespace App;

final class Calculator
{
    public function add(int $a, int $b): int
    {
        return $a + $b;
    }
}

DataProvidersを使用しなければ、アサーションを4回書く必要があり、少し手間です。

tests/CalculatorTest.php
<?php

namespace App\Tests;

use PHPUnit\Framework\TestCase;
use App\Calculator;

final class CalculatorTest extends TestCase
{
    private Calculator $calculator;

    protected function setUp(): void
    {
        // setUpはテストメソッドが実行される前に実行される
        $this->calculator = new Calculator();
    }

    public function testAdd(): void
    {
        $this->assertSame(2, $this->calculator->add(1, 1));
        $this->assertSame(3, $this->calculator->add(1, 2));
        $this->assertSame(4, $this->calculator->add(1, 3));
        $this->assertSame(5, $this->calculator->add(1, 4));
    }
}

テスト結果

4回テストしていますが、PHPUnitではテストメソッドを1つのテストとしてカウントするため、今回のtestAdd()のように1つのメソッドで複数アサーションを書いた場合でも、出力は1つの.になります。

PHPUnit 12.1.4 by Sebastian Bergmann and contributors.

Runtime:       PHP 8.4.4

.                                                                   1 / 1 (100%)

Time: 00:00.033, Memory: 8.00 MB

OK (1 test, 4 assertions)

DataProvidersを使用した場合

アサーションを1つ書くだけで良くなり、コードがすっきりして可読性が上がります。

tests/CalculatorTest.php
<?php

namespace App\Tests;

use PHPUnit\Framework\TestCase;
use PHPUnit\Framework\Attributes\DataProvider;
use App\Calculator;

final class CalculatorTest extends TestCase
{
    private Calculator $calculator;

    protected function setUp(): void
    {
        // setUpはテストメソッドが実行される前に実行される
        $this->calculator = new Calculator();
    }

    public static function additionProvider(): array
    {
        return [
            [0, 0, 0],
            [0, 1, 1],
            [1, 0, 1],
            [1, 1, 2],
        ];
    }

    #[DataProvider('additionProvider')]
    public function testAdd(int $a, int $b, int $expected): void
    {
        // $a には各配列の1番目の要素が入る
        // $b には2番目の要素が入る
        // $expected には3番目の要素が入る
        $this->assertSame($expected, $this->calculator->add($a, $b));
    }
}

テスト結果

DataProvidersを使用すると、個別のテストケースとして扱われるため、どの入力で失敗したかがログや出力で明確に分かるようになります。

PHPUnit 12.1.4 by Sebastian Bergmann and contributors.

Runtime:       PHP 8.4.4

....                                                                4 / 4 (100%)

Time: 00:00.022, Memory: 8.00 MB

OK (4 tests, 4 assertions)

外部DataProvidersの使用方法

DataProvidersを別ファイルに定義して管理することで、テストクラスの記述をより簡潔に保ち、複数のテストで再利用しやすくなります。

tests/DataProvider/ExternalCalculatorDataProvider.php
<?php

namespace App\Tests\DataProvider;

final class ExternalCalculatorDataProvider
{
    public static function additionProvider(): array
    {
        return [
            [0, 0, 0],
            [0, 1, 1],
            [1, 0, 1],
            [1, 1, 2],
        ];
    }
}

DataProvidersからDataProviderExternalに変更しないと動作しないため、その点に注意してください。

tests/CalculatorTest.php
<?php

namespace App\Tests;

use PHPUnit\Framework\TestCase;
use PHPUnit\Framework\Attributes\DataProviderExternal;
use App\Calculator;
use App\Tests\DataProvider\ExternalCalculatorDataProvider;

final class CalculatorTest extends TestCase
{
    private Calculator $calculator;

    protected function setUp(): void
    {
        // setUpはテストメソッドが実行される前に実行される
        $this->calculator = new Calculator();
    }

    #[DataProviderExternal(ExternalCalculatorDataProvider::class, 'additionProvider')]
    public function testAdd(int $a, int $b, int $expected): void
    {
        $this->assertSame($expected, $this->calculator->add($a, $b));
    }
}

まとめ

DataProvidersは、同じテストメソッドを複数のデータセットで繰り返し実行できる便利な機能です。
これによりテストコードの重複を減らし、可読性や保守性が向上します。
また、外部DataProvidersを使えば、データの再利用や整理が容易になり、より柔軟なテスト設計が可能になります。
積極的に活用して、効率的なテストコードを書いていきましょう。

参考資料

Discussion