[Osaka/Yokohama/Tokushima] Looking for infrastructure/server side engineers!

[Osaka/Yokohama/Tokushima] Looking for infrastructure/server side engineers!

[Deployed by over 500 companies] AWS construction, operation, maintenance, and monitoring services

[Deployed by over 500 companies] AWS construction, operation, maintenance, and monitoring services

[Successor to CentOS] AlmaLinux OS server construction/migration service

[Successor to CentOS] AlmaLinux OS server construction/migration service

[For WordPress only] Cloud server “Web Speed”

[For WordPress only] Cloud server “Web Speed”

[Cheap] Website security automatic diagnosis “Quick Scanner”

[Cheap] Website security automatic diagnosis “Quick Scanner”

[Reservation system development] EDISONE customization development service

[Reservation system development] EDISONE customization development service

[Registration of 100 URLs is 0 yen] Website monitoring service “Appmill”

[Registration of 100 URLs is 0 yen] Website monitoring service “Appmill”

[Compatible with over 200 countries] Global eSIM “Beyond SIM”

[Compatible with over 200 countries] Global eSIM “Beyond SIM”

[If you are traveling, business trip, or stationed in China] Chinese SIM service “Choco SIM”

[If you are traveling, business trip, or stationed in China] Chinese SIM service “Choco SIM”

[Global exclusive service] Beyond's MSP in North America and China

[Global exclusive service] Beyond's MSP in North America and China

[YouTube] Beyond official channel “Biyomaru Channel”

[YouTube] Beyond official channel “Biyomaru Channel”

【PHPUnit12に備えろ】[ INFO ] No tests found ←これ【dataProvider】

【PHPUnit12に備えろ】[ INFO ] No tests found ←これ【dataProvider】

はじめに

システム開発部の榎木です。
今回は dataProvider を使ったらテスト実行時に INFO No tests found.と出てきた際の解決法について記述します。
茶番が長いので、答えだけ知りたい人は結論だけ見てください。

本編

ことのはじまり

※ この記事において、テスト内容は微塵も重要ではないので、テストの体を成していないことは気にしないでください。

ぼく「テスト書くか~、、、このテスト内容なら dataProvider でええな!」
ぼく「フンッ」
<?php

namespace Tests\Unit;

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

class DataProviderTest extends TestCase
{
    /**
    * @return array
    */
    public function provideParam(): array
    {
        return[
            'params' => ['data', 'true'],
        ];
    }

    /**
    * @dataProvider provideParam
    */
    public function test_データプロバイダーのテスト($data, $expected)
        $this->assertTrue(true);
    }
}
root:/var/www/html/src# php artisan test tests/Unit/DataProviderTest.php

WARN Metadata found in doc-comment for method Tests\Unit\DataProviderTest::test_データプロバイダーのテスト(). 
Metadata in doc-comments is deprecated and will no longer be supported in PHPUnit 12.
Update your test code to use attributes instead.

INFO No tests found.

ぼく「ん?」
ぼく「はえ~ PHPUnit12 からは Doc じゃなくて属性で指定するんやな!わかったで!」
※属性はこれ→ #[]

#[DataProvider('provideParam')]
public function test_データプロバイダーのテスト($data, $expected)
{
  $this->assertTrue(true);
}

ぼく「ほいよ」
ぼく「実行っと」

root:/var/www/html/src# php artisan test tests/Unit/DataProviderTest.php

INFO No tests found.

ぼく「ゑ?」

本題

茶番がなげーよという声が聞こえてきそうですね。
さておきとにかく、ここで重要なのは「テストが見つからない」と言われていることです。

こういうとき皆さんはどうされるでしょうか。
とりあえず php artisan optimize:clear とか、composer dump-autoload とか、
namespaceやファイル名の見直しとか、そういうことをされるんじゃないでしょうか。(してください。)

私も当然のごとく「あ~いつものアレね」くらいの感覚でした。
しかしこの記事を書くということはこれまた当然のことながら直らなかったわけです。

ここで思い出してほしいのが、あくまで INFO として出てきたということです。
通常、存在しないテストを指定・実行すると下記のようになります。
root:/var/www/html/src# php artisan test tests/Unit/NoneTest.php
PHPUnit 11.2.2 by Sebastian Bergmann and contributors.

Test file "tests/Unit/NoneTest.php" not found

ということはテストはきちんと存在しているはずなのに見つからないのです。
次に私は、適当なテストを作ってこの説が正しいのかを確認してみました。
<?php

namespace Tests\Unit;

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

class DataProviderTest extends TestCase
{
    /**
    * @return array
    */
    public function provideParam(): array
    {
        return[
            'params' => ['data', 'true'],
        ];
    }

    public function test_適当なテスト()
    {
        $this->assertTrue(true);
    }

    #[DataProvider('provideParam')]
    public function test_データプロバイダーのテスト($data, $expected)
    {
        $this->assertTrue(true);
    }
}
root:/var/www/html/src# php artisan test tests/Unit/DataProviderTest.php
FAIL Tests\Unit\DataProviderTest
⨯ データプロバイダーのテスト
✓ 適当なテスト 0.06s 
───────────────────────────────────────────────────────────────────────────────────────────────────────────── 
FAILED Tests\Unit\DataProviderTest > データプロバイダーのテスト 
The data provider specified for Tests\Unit\DataProviderTest::test_データプロバイダーのテスト is invalid
Data Provider method Tests\Unit\DataProviderTest::provideParam() is not static

Tests: 1 failed, 1 passed (1 assertions)
Duration: 0.10s

思った以上の成果が得られました。ファイルはおろかテストも認識されています。
しかも正確なエラー付きです。
どうやら dataProvider メソッド を static で作って欲しいようです。
エラーに従うロボットになります。

<?php

namespace Tests\Unit;

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

class DataProviderTest extends TestCase
{
    /**
    * @return array
    */
    public static function provideParam(): array
    {
        return[
            'params' => ['data', 'true'],
        ];
    }

    #[DataProvider('provideParam')]
    public function test_データプロバイダーのテスト($data, $expected)
    {
        $this->assertTrue(true);
    }
}

root:/var/www/html/src# php artisan test tests/Unit/DataProviderTest.php

PASS Tests\Unit\DataProviderTest
✓ データプロバイダーのテスト with data set "params" 0.06s

Tests: 1 passed (1 assertions)
Duration: 0.09s

通りましたね!
どうやら dataProvider として使うメソッドは、static にしてあげれば求める挙動はしてくれそうです。
ひとまずは解決しましたが、「INFO No tests found.」の謎を追求してみたいと思います。

原因の追究

これまでの情報でわかっていることの中で立てられる仮説は、「dataProviderとして使うメソッドは static でなければならない」ということです。
ここで、一番最初の実行結果が参考になります。

root:/var/www/html/src# php artisan test tests/Unit/DataProviderTest.php WARN Metadata found in doc-comment for method Tests\Unit\DataProviderTest::test_データプロバイダーのテスト().
Metadata in doc-comments is deprecated and will no longer be supported in PHPUnit 12.
Update your test code to use attributes instead. INFO No tests found. 

御覧の通り、Doc コメントで dataProvider を使用するのは、まだ "非推奨" なだけなので WARN です。
ということは、dataProvider メソッドさえ static なら正常に実行できるのではないかと考えられます。

<?php

namespace Tests\Unit;

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

class DataProviderTest extends TestCase
{
    /**
    * @return array
    */
    public static function provideParam(): array
    {
        return[
            'params' => ['data', 'true'],
        ];
    }

    /**
    * @dataProvider provideParam
    */
    public function test_データプロバイダーのテスト($data, $expected)
    {
        $this->assertTrue(true);
    }
}

 

root:/var/www/html/src# php artisan test tests/Unit/DataProviderTest.php

WARN Metadata found in doc-comment for method Tests\Unit\DataProviderTest::test_データプロバイダーのテスト().
Metadata in doc-comments is deprecated and will no longer be supported in PHPUnit 12.
Update your test code to use attributes instead.

PASS Tests\Unit\DataProviderTest
✓ データプロバイダーのテスト with data set "params" 0.09s

Tests: 1 passed (1 assertions)
Duration: 0.14s

仮説通り正常に実行できましたね。
しかしながら、なぜ static である必要があるのでしょうか。私の記憶とソースコードを見るに以前は static である必要はなかったはずです。
ということで調べてみました。
〇引用:https://docs.phpunit.de/en/10.5/writing-tests-for-phpunit.html#data-providers

原文
A data provider method must be public and static.
It must return a value that is iterable, either an array or an object that implements the Traversable interface.
翻訳
データプロバイダメソッドは、public かつ static でなければなりません。
反復可能な値(配列またはTraversableインターフェースを実装したオブジェクト)を返さなければなりません。

ということらしいです。変化についていきましょう。
さらに下記のような記述もありました。

原文
When a test depends on a test that uses data providers, the depending test will be executed when the test it depends upon is successful for at least one data set.
The result of a test that uses data providers cannot be injected into a depending test.
翻訳
テストがデータプロバイダを使用するテストに依存している場合、依存するテストは、依存するテストが少なくとも1つのデータセットで成功した場合に実行されます。
データプロバイダを使用するテストの結果は、依存するテストには注入されません。

適当なテストを入れたらエラーが出てきた理由はこれみたいです。
いわれてみたら「はい!仰る通りでございます!」というぐうの音も出ない正論パンチです。
テスト以前の部分で失敗してそれを前提としたテストしか存在しないなら「No tests found.」は至極当然です。

結論

dataProvider の対象メソッドは staticメソッド にしてください。

余談

なんで static である必要があるの?
という疑問が出てきます。

(なぜおまえの感想なんだエンジニアならソースを出せと言われることに怯えて震えています。)
おそらく「テストデータのテストからの独立性の担保」ではないかなと考えています。
再現性と他テストに影響を与えないことはテストにおいてとても重要なことであり、インスタンスの状態に依存しない純粋なデータを提供することを保証できます。

色々と公式のソースを漁ってみたのですが、static にしてね!というアップデートに際した情報は散見されました。
しかしながら、なぜ static にすることを強制しだしたのかという理由に関する部分は見つけられませんでした、、、
(ご存じの方いらしたらぜひご教示いただきたいです)
この記事がお役に立てば【 いいね 】のご協力をお願いいたします!
8
読み込み中...
8 票, 平均: 1.00 / 18
135
X facebook はてなブックマーク pocket
[2025.6.30 Amazon Linux 2 support ended] Amazon Linux server migration solution

[2025.6.30 Amazon Linux 2 support ended] Amazon Linux server migration solution

[Osaka/Yokohama] Actively recruiting infrastructure engineers and server side engineers!

[Osaka/Yokohama] Actively recruiting infrastructure engineers and server side engineers!

The person who wrote this article

About the author

Enoki

I play everything from FPS, RPG, MMO, crafting, etc.