💨

PHPUnit9のデータプロバイダメソッドに引数の指定ができるぞ!(でも、PHPUnit10では非推奨、PHPUnit11以降は使えない)

2023/11/14に公開

はじめに

PHPUnit9までのデータプロバイダメソッドに引数の指定ができる事にたまたま気づいたので調査結果を残しておきます。

環境

  • PHP 8.2.12

さっそく確認してみる

つぎの検証用コードで確認してみます。

PHPUnit9DataProviderMethodTest.php
<?php

declare(strict_types=1);

namespace Tests;

use PHPUnit\Framework\TestCase;

class PHPUnit9DataProviderMethodTest extends TestCase
{
    public function provider(string $a): array
    {
        fwrite(STDOUT, $a . PHP_EOL);
        return [
            [1],
        ];
    }

    /**
     * @dataProvider provider
     */
    public function testMethod(int $a)
    {
        $this->assertSame(1, $a);
    }
}
% ./vendor/bin/phpunit tests/PHPUnit9DataProviderMethodTest.php
testMethod
PHPUnit 9.6.13 by Sebastian Bergmann and contributors.

.                                                                   1 / 1 (100%)

Time: 00:00.005, Memory: 4.00 MB

OK (1 test, 1 assertion)

testMethodと表示しているので、データプロバイダメソッドにテストメソッドの名前を渡していることがこれで分かりますね。

※データプロバイダの動くタイミングはこちらの記事を参照してください。

https://zenn.dev/naopusyu/articles/42d393c1c1b4bc

なぜテストメソッド名を渡せるのか?

PHPDocのアノテーションを解析するコードにバッチリ書いてありました。

https://github.com/sebastianbergmann/phpunit/blob/9.6.13/src/Util/Annotation/DocBlock.php#L420-L424

引数の有無を判定し、引数があれば$methodName変数を指定するようになっている。
この$methodName変数にテストメソッド名が設定されているようです。

そもそも、なぜ引数に指定できていたのか

GitHubから履歴を追いかけてみたところ、追加したコミットは見つけましたがなぜ指定できるかまでは不明でした。

https://github.com/sebastianbergmann/phpunit/commit/9815a05d52a7c969a791aca17c3b8cb30f3589bc

issues、pull requestを探しても見当たらない。

でも、PHPUnit 10では非推奨、PHPUnit 11以降は使えない

調べていると、PHPUnit 10で非推奨にしているコミットがあり、PHPUnit 11でサポートしないってissuesがありました。

https://github.com/sebastianbergmann/phpunit/commit/9caafe2d49b33a21f87db248a8ad6ca7c7bdac09

https://github.com/sebastianbergmann/phpunit/issues/5100

※PHPUnit 10で確認したテストクラス

PHPUnit10DataProviderMethodTest.php
<?php

declare(strict_types=1);

namespace Tests;

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

class PHPUnit10DataProviderMethodTest extends TestCase
{
    public static function provider(string $a): array
    {
        fwrite(STDOUT, $a . PHP_EOL);
        return [
            [1],
        ];
    }

    #[DataProvider('provider')]
    public function testMethod(int $a)
    {
        $this->assertSame(1, $a);
    }
}

% ./vendor/bin/phpunit tests/PHPUnit10DataProviderMethodTest.php
provider
PHPUnit 10.4.2 by Sebastian Bergmann and contributors.

Runtime:       PHP 8.2.12

D                                                                   1 / 1 (100%)

Time: 00:00.006, Memory: 6.00 MB

1 test triggered 1 PHPUnit deprecation:

1) Tests\PHPUnit10DataProviderMethodTest::testMethod
Data Provider method Tests\PHPUnit10DataProviderMethodTest::provider() expects an argument

tests/PHPUnit10DataProviderMethodTest.php:24

OK, but there were issues!
Tests: 1, Assertions: 1, Deprecations: 1.

動いているはいけるけど、非推奨のDという結果になりましたね。

また、テストメソッド名ではなく、データプロバイダメソッド名が表示しているので引数の値自体が変わっているです。
なので、PHPUnit 9までのデータプロバイダの引数の値に依存したテストは失敗することになりますね。

https://github.com/sebastianbergmann/phpunit/blob/10.4.2/src/Metadata/Api/DataProvider.php#L164

まとめ

知らなくてもテストは書けるし、知っていても使わないと思うので一体何のために指定できるようにしたのかは謎でした。(深く調べればわかるかもですが、そこまで頑張れなかった。)

まぁPHPUnit 10からデータプロバイダメソッドはstaticメソッドを推奨しているし、
アノテーションではなく、アトリビュートを使うように変更が入りますし、その過程で廃止になったのかもしれないですね。

https://github.com/sebastianbergmann/phpunit/issues/4502

こんなことがありますって感じのネタ記事でした。

GitHubで編集を提案

Discussion