skills17 / phpunit-helpers
此包为技能竞赛环境提供了一些PHPUnit辅助工具。
Requires
- php: >=7.4
- phpunit/phpunit: ^9
Requires (Dev)
- perchten/rmrdir: ^1.0
- squizlabs/php_codesniffer: ^3.5
README
此包为技能竞赛环境提供了一些PHPUnit辅助工具。它包括:
- 自定义输出格式化器
- 基本测试类
- 自动数据库重置
- ...以及其他更多
目录
安装
需求:
- PHPUnit
9.0
或更高版本 - PHP
7.4
或更高版本
要安装此包,只需运行以下命令
composer require skills17/phpunit-helpers
此外,在您的任务根目录中创建一个 phpunit.xml
文件
<?xml version="1.0" encoding="UTF-8"?> <phpunit cacheResultFile="vendor/phpunit/phpunit.cache" convertErrorsToExceptions="true" convertNoticesToExceptions="true" convertWarningsToExceptions="true" processIsolation="false" stopOnFailure="false" printerClass="Skills17\PHPUnit\ResultPrinter" printerFile="vendor/skills17/phpunit-helpers/src/Printer.php" colors="true" > <testsuites> <testsuite name="Tests"> <directory>./tests/</directory> </testsuite> </testsuites> </phpunit>
要使用提供的结果打印机,需要 printerClass
和 printerFile
设置。其他设置是建议设置,但可以根据需求进行修改。
建议添加两个额外的Composer脚本,以便可以通过执行 composer test
或 composer test:json
来运行测试。
"scripts": { "test": "phpunit --colors=always", "test:json": "FORMAT=json phpunit | tail -n +3" },
使用
需要创建一个包含有关任务信息的 config.json
文件。它应放置在您的任务根目录中,与 composer.json
文件相邻。
分组
一个核心概念是测试组。通常,您不希望在单个测试函数中测试一个标准下的所有内容,而是将其拆分为多个以获得更清晰的测试类和更好的概览。
在PHP中,测试通过在 config.json
文件中定义的函数前缀进行分组。
例如,如果您有一个标准,即 GET /countries
实现正确并且奖励3分,您可以有以下测试函数:
testCountriesIndexAll
:测试是否返回了所有可用的国家testCountriesIndexLimit
:测试是否尊重可选的限制testCountriesIndexSearch
:测试是否可以通过可选的查询搜索国家
现在,所有这些函数都有一个共同的名称前缀:CountriesIndex
(可以省略 test
),而 config.json
将类似于以下内容:
{ "groups": [ { "match": "CountriesIndex.+" } ] }
每个测试方法现在如果通过将获得1分,整个组总共获得3分。如果您想使 所有 三个测试函数都必须通过才能获得3分(否则为0分),可以设置 "required": true
属性。
非数据库测试
要为不需要数据库的应用程序或其部分编写测试,可以简单扩展 Skills17\PHPUnit\BaseTest
类。它进一步扩展了PHPUnit的正常 TestCase
类,因此所有PHPUnit断言函数都可用。
数据库测试
如果测试中的应用程序需要数据库,则应在每次测试运行之前将其重置,以确保数据在多次测试运行中保持一致。为此,有两个可扩展的类可用。
此外,如果数据库转储没有默认名称,则需要提供一个并指定在 config.json
中。
读取测试
如果测试和被测试的应用程序部分仅从数据库中读取数据,而从不写入或更改它,则应扩展 Skills17\PHPUnit\Database\ReadTest
类。
为了提高性能,此类测试仅在测试类执行之前重置数据库一次。
编写测试
如果测试或被测试的应用程序部分写入数据(插入、更新、删除),则应该扩展 Skills17\PHPUnit\Database\WriteTest
类。
这确保了在每个测试函数执行之前,数据库都会被重置,而不仅仅是在类开始时像读取测试那样重置一次。这确保了每个函数都从一个全新的数据库转储开始,这对于上一个函数失败导致数据库处于未知状态或仅执行函数子集时特别有用。
额外测试
为了防止作弊,可以使用额外的测试。这些测试对竞争者不可用,并且应该与正常测试完全相同,但使用不同的值。
例如,如果您的正常测试包含一个检查以通过'Sw*'搜索所有国家的列表,则将测试复制到额外的测试中,并将搜索字符串更改为'Ca*'。由于竞争者不知道额外的测试,它将检测到静态返回值,这些返回值只是为了满足'Sw*'测试而返回,而不是实际实现搜索逻辑。
额外的测试通过它们的命名空间来检测,命名空间应包含 \Extra\
。这意味着,如果您的正常测试在 Skills17\CountriesApp\Test
命名空间中,则额外的测试可以位于 Skills17\CountriesApp\Test\Extra
。类和方法名称应与正常测试中的名称完全相同。如果它们不匹配,将显示警告。
如果额外的测试失败而相应的正常测试通过,将显示警告,需要手动审查该测试,因为它检测到可能的作弊行为。然后必须根据具体情况手动决定处罚,假设测试已通过且没有作弊,输出中可见的分数。
对于将任务分配给竞争者,只需删除包含所有额外测试的文件夹即可。不需要执行或配置其他操作。
输出
当环境变量 FORMAT
设置为 json
时,结果将以 json 格式打印。否则,将可见一个格式良好的摘要。
setUp
固定装置
如果您在自己的测试类中覆盖了 setUp
固定方法,请确保调用父方法。
public function setUp(): void { parent::setUp(); // your own code here }
最佳实践
时间限制
强烈建议对测试强制执行时间限制。否则,无限循环可能会破坏整个测试管道。
以下步骤显示了如何配置时间限制。
- 安装 composer 包
phpunit/php-invoker
- 将
enforceTimeLimit="true"
添加到phpunit.xml
配置文件中 - 将所有测试用例注释为
@large
(60秒超时)、@medium
(10秒超时)或@small
(1秒超时)
可以配置所有测试大小的超时时间。配置超时时间。
编写良好的测试
有关在竞赛环境中编写良好测试的额外建议,请阅读这篇博客文章。