[准备 PHPUnit12] [信息] 未找到测试 ←此 [数据提供程序]

[准备 PHPUnit12] [信息] 未找到测试 ←此 [数据提供程序]

介绍

我是系统开发部的榎木。
这次,我将解释如何解决使用数据提供程序运行测试时收到“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_DataProviderTest($data, $expected) $this->assertTrue(true); } }
root:/var/www/html/src# php artisan test tests/Unit/DataProviderTest.php 警告:在 Tests\Unit\DataProviderTest::test_DataProviderTest() 方法的文档注释中发现了元数据。文档注释中的元数据已被弃用,PHPUnit 12 将不再支持此功能。请更新您的测试代码以使用属性。 信息:未找到测试。.

我:“啊?”
我:“哇,原来从 PHPUnit12 开始,要用属性而不是 Doc 来指定啊!明白了!”
※属性是这样的 → #[]

#[DataProvider('provideParam')] public function test_DataProviderTest($data, $expected) { $this->assertTrue(true); }

我:“开始了。”
我:“开始吧。”

root:/var/www/html/src# php artisan test tests/Unit/DataProviderTest.php INFO 未找到测试。.

我:“啊?”

主题

我知道有些人会说这是个冗长的笑话。总之,重点是它显示“找不到测试”。遇到这种情况该怎么办?你可能会尝试运行 `php artisan optimize:clear`、`composer dump-autoload`,或者检查命名空间和文件名。(请务必这样做。)当然,我一开始也想:“哦,又是老问题。” 然而,我写这篇文章就意味着,这个问题显然还没有解决。我想让你记住的是,它只显示为 INFO 信息。通常情况下,当你指定并运行一个不存在的测试时,会出现以下信息:
root:/var/www/html/src# php artisan test tests/Unit/NoneTest.php PHPUnit 11.2.2 by Sebastian Bergmann and contributors. 未找到测试文件“tests/Unit/NoneTest.php”。

这意味着该测试必然存在,但却找不到。接下来,我创建了一个合适的测试来验证这个理论是否正确。
<?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 失败 Tests\Unit\DataProviderTest ⨯ 数据提供程序测试 ✓ 测试合适 0.06秒 ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── 失败 Tests\Unit\DataProviderTest > 数据提供程序测试 为 Tests\Unit\DataProviderTest::test_dataprovider 测试指定的数据提供程序无效 数据提供程序方法 Tests\Unit\DataProviderTest::provideParam() 不是静态的 测试:1 个失败,1 个通过(1 个断言) 持续时间:0.10秒

这比我预期的要好得多。它不仅识别出了文件,甚至还识别出了测试,
并给出了精确的错误信息。
它似乎想让我把 dataProvider 方法设为静态方法。
接下来会有一个机器人来跟踪这个错误。

<?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 ✓ 使用数据集“params”测试数据提供程序 0.06秒 测试:1 个通过(1 个断言) 持续时间:0.09秒

测试通过了!
看来如果将用作数据提供程序的方法设为静态方法,它就能按预期工作了。
目前问题已经解决,但我还想探究一下“INFO No tests found”这条信息背后的原因。

调查原因

根据我们目前掌握的信息,我们可以假设用作数据提供程序的方法必须是静态的。
这里,第一次执行结果将有所帮助。

root:/var/www/html/src# php artisan test tests/Unit/DataProviderTest.php 警告:在 Tests\Unit\DataProviderTest::test_DataProviderTest() 方法的文档注释中发现了元数据。文档注释中的元数据已被弃用,PHPUnit 12 将不再支持此功能。请更新您的测试代码以使用属性。 信息:未找到测试。. 

如您所见,文档注释指出使用 dataProvider 仍然“已弃用”,因此这是一个警告。
这意味着如果 dataProvider 方法是静态的,则应该可以正常运行。

<?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 警告:在方法 Tests\Unit\DataProviderTest::test_DataProviderTest() 的文档注释中发现了元数据。文档注释中的元数据已被弃用,PHPUnit 12 将不再支持。请更新您的测试代码以使用属性代替。通过 Tests\Unit\DataProviderTest ✓ 使用数据集“params”的 DataProvider 测试 0.09 秒 测试:1 个通过(1 个断言) 持续时间:0.14 秒

正如预期的那样,测试运行成功了。
但是,为什么需要静态数据呢?凭我的记忆和查看源代码来看,之前并不需要静态数据。
所以我研究了一下。
引用: https://docs.phpunit.de/en/10.5/writing-tests-for-phpunit.html#data-providers

公共的
且静态的。
它必须返回一个可迭代的值,可以是数组,也可以是实现了 Traversable 接口的对象。
翻译
数据提供程序方法必须是公共的、静态的,并且必须返回一个可迭代的值(数组或实现了 Traversable 接口的对象)。

看来确实如此。让我们持续关注这些变化。
此外,还有以下描述:


一个测试依赖于另一个使用数据提供程序的测试时,依赖测试只有在被依赖的测试至少在一个数据集上成功通过后才会执行。
使用数据提供程序的测试结果不能注入到依赖测试中。
翻译
测试依赖于使用数据提供程序的测试,则只有当依赖测试在至少一个数据集上成功时,才会执行依赖测试。使用数据提供程序的测试结果不会被注入到依赖测试中。

这似乎就是我输入随机测试时出错的原因。
这真是一个完全合理的答案,让我哑口无言:“没错!完全正确!”
如果测试的前一部分失败了,而唯一存在的测试又是基于这个假设的,那么出现“未找到测试”的提示也就不足为奇了。

结论

dataProvider 的目标方法必须是静态方法。

附注

为什么一定要静态?
 (如果你是工程师,你可能正害怕被要求提供源代码,所以你为什么会有这种看法?)我认为可能是为了“确保测试数据与其他测试的独立性”。可复现性和不影响其他测试在测试中非常重要,而静态数据可以保证提供不依赖于实例状态的纯净数据。我查阅了各种官方资料,只找到一些关于“必须静态!”的更新信息。然而,我找不到任何关于他们为什么开始强制要求静态数据的信息……(如果有人知道,请告诉我。)
如果您觉得这篇文章有用,请点击【点赞】!
12
加载中...
12票,平均分:1.00/112
1,457
X Facebook Hatena书签 口袋

这篇文章的作者

关于作者

榎木

我什么游戏都玩,包括第一人称射击游戏、角色扮演游戏、大型多人在线游戏和建造类游戏。