[Prepare for PHPUnit12] [INFO] No tests found ←This [dataProvider]

table of contents
[Prepare for PHPUnit12] [INFO] No tests found ←This [dataProvider]
Introduction
This is Enoki from the System Development Department.
This time, I'll describe how to resolve the "INFO No tests found." error that appears when running tests using dataProvider.
The explanation is long, so if you just want the answer,the conclusionplease skip to
Main Story
The beginning
*Please ignore the fact that the test content is not at all important in this article, so don't worry about it not being a proper test.
Me: "Let's write a test... For this test content, dataProvider will do!" Me: "Hmph."
<?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_DataProviderTest($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_DataProviderTest(). 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.
Me: "Huh?"
Me: "Wow, so from PHPUnit12 onwards, you specify it with an attribute instead of a doc! I get it!"
*The attribute is this → #[]
#[DataProvider('provideParam')] public function test_DataProviderTest($data, $expected) { $this->assertTrue(true); }
Me: "Okay."
Me: "Let's do it."
root:/var/www/html/src# php artisan test tests/Unit/DataProviderTest.php INFO No tests found.
Me: "Huh?"
Main topic
I can almost hear people saying, "This farce is dragging on." Anyway, the important thing here is that it says "test not found." What do you all do in a situation like this? I suppose you would try something like `php artisan optimize:clear` or `composer dump-autoload`, or review the namespace and file names. (Please do.) Naturally, I also had the feeling of "Oh, it's the usual thing." But the fact that I'm writing this article means, naturally, that it wasn't fixed. What I want you to remember here is that it appeared as INFO. Normally, if you specify and run a test that doesn't exist, it will look like this:
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
This means that the test must exist, but it cannot be found. Next, I created a suitable test to see if this theory was correct
<?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_Appropriate test() { $this->assertTrue(true); } #[DataProvider('provideParam')] public function test_Data provider test($data, $expected) { $this->assertTrue(true); } }
root:/var/www/html/src# php artisan test tests/Unit/DataProviderTest.php FAIL Tests\Unit\DataProviderTest ⨯ Data provider test ✓ Appropriate test 0.06s ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────── FAILED Tests\Unit\DataProviderTest > Data provider test The data provider specified for Tests\Unit\DataProviderTest::test_dataprovider test is invalid Data Provider method Tests\Unit\DataProviderTest::provideParam() is not static Tests: 1 failed, 1 passed (1 assertions) Duration: 0.10s
The results were better than expected. Not only are the files recognized, but the tests are too.
And they even come with accurate errors.
It seems they want the `dataProvider` method to be static.
It will become a robot that follows the errors.
<?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_DataProviderTest($data, $expected) { $this->assertTrue(true); } }
root:/var/www/html/src# php artisan test tests/Unit/DataProviderTest.php PASS Tests\Unit\DataProviderTest ✓ Test of data provider with data set "params" 0.06s Tests: 1 passed (1 assertions) Duration: 0.09s
It worked!
It seems that if we make the method used as a dataProvider static, it will behave as we want.
The problem is solved for now, but I'd like to investigate the mystery of "INFO No tests found."
Investigating the cause
Based on the information we have so far, the hypothesis we can make is that "methods used as dataProviders must be static."
The very first execution result is helpful here.
root:/var/www/html/src# php artisan test tests/Unit/DataProviderTest.php WARN Metadata found in doc-comment for method Tests\Unit\DataProviderTest::test_DataProviderTest(). 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.
As you can see, using `dataProvider` in Doc comments is only a WARN because it's still "deprecated".
This suggests that if the `dataProvider` method is static, it should execute correctly.
<?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_DataProviderTest($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_DataProviderTest(). 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 ✓ DataProvider test with data set "params" 0.09s Tests: 1 passed (1 assertions) Duration: 0.14s
The test executed successfully, just as I hypothesized.
However, why does it need to be static? From my memory and looking at the source code, it didn't need to be static before.
So I investigated.
(Reference:https://docs.phpunit.de/en/10.5/writing-tests-for-phpunit.html#data-providers
public
and static.
It must return a value that is iterable, either an array or an object that implements the Traversable interface.
Translation
data provider methods must be public and static. They must return an iterable value (an array or an object that implements the Traversable interface).
That seems to be the case. Let's keep up with the changes.
Furthermore, there was also the following statement:
Original textWhen
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.
a translation
test depends on a test that uses a data provider, the dependent test will only run if the dependent test succeeds on at least one dataset. The results of the test that uses the data provider are not injected into the dependent test.
It seems this is the reason why I got an error when I added a suitable test.
When you think about it, it's an undeniable truth that leaves you speechless.
If there's a failure in the part before the test and the only tests that exist are those that assume that failure, then "No tests found" is perfectly natural.
conclusion
The target method of dataProvider must be a static method
A side note
why does it need to be static? (I'm trembling with fear of being told, "Why are you just giving your opinion? As an engineer, you should provide the source code.") I suspect it's to "ensure the independence of test data from other tests." Reproducibility and not affecting other tests are very important in testing, and it ensures that pure data is provided that does not depend on the state of the instance. I've searched through various official sources, and I found information about the update that said, "Make it static!" However, I couldn't find anything about the reason why they started forcing it to be static... (If anyone knows, I would really appreciate it if you could let me know.)
12
