antonioprimera / phpunit-custom-assertions
自定义测试断言,目前尚未包含在PHPUnit中。
Requires (Dev)
- antonioprimera/lara-packager: ^1.5
- illuminate/contracts: ^8.0
- illuminate/support: ^8.0
- orchestra/testbench: ^6.0
This package is auto-updated.
Last update: 2024-09-16 21:41:29 UTC
README
如果你是一个严肃的TDD爱好者,你可能会遇到需要特殊断言方法的情况。
这是一个我尝试收集一些对PHPUnit测试有用的自定义断言的包。此包依赖于Laravel的Illuminate\Support和Illuminate\Contracts,主要面向Laravel测试,但也应在裸骨PHPUnit环境中运行良好。
目前,以下断言类别得到了覆盖
- 文件内容断言
- 文件和文件夹存在性
- 列表比较(数组、迭代器、Laravel集合等)
安装
通过Composer导入
composer require --dev antonioprimera/phpunit-custom-assertions
然后在你的测试用例中仅使用trait AntonioPrimera\Testing\CustomAssertions
。
使用方法
在测试用例中包含trait AntonioPrimera\Testing\CustomAssertions
后,你可以在测试中直接调用此包中包含的任何断言方法。
以下是一个简短的例子,涵盖了此包中的大多数断言
namespace AntonioPrimera\Testing\Tests\Unit; use AntonioPrimera\Testing\CustomAssertions; use PHPUnit\Framework\TestCase; class FileAssertionsTest extends TestCase { use CustomAssertions; /** @test */ public function it_can_do_any_of_the_implemented_assertions() { //you can call any of the assertions as instance methods, functions or static methods $this->assertFileContains('CustomAssertions', __FILE__); assertFileContains(['namespace', 'use'], __FILE__); static::assertFileContentsEquals('abc', __FILE__, function($str) { return 'abc'; }); //compares two lists $this->assertListsEqual(['a', 1, [true, null, collect([0, 5])]], [[null, true, [5,0]], 1,'a']); //the following assertion is expected to fail, containing the messages given as parameters $this->expectAssertionToFail(__FILE__ . '.js'); $this->assertFilesExist([__FILE__, __FILE__ . '.js']); } }
由于断言是基于基本的PHPUnit框架约束编写的,因此所有断言都可以作为静态方法调用
static::assertFileContains($string, $filePath);
作为实例方法
$this->assertFileContains($string, $filePath);
或作为函数
assertFileContains($string, $filePath);
可用的断言
文件和文件夹
assertFileContains(string | array $subString, string $filePath, [callable $processor])
此断言检查给定路径的文件$filePath是否包含字符串$subString。
为了方便使用,你可以通过提供一个字符串数组作为第一个参数($substring),来检查文件是否包含多个字符串。
$this->assertFileContains('namespace', $filePath); $this->assertFileContains(['namespace', 'class'], $filePath);
如果你想处理文件内容和字符串,在检查之前,你可以提供可调用的字符串处理器(一个函数或方法)作为第三个参数。可调用的接收一个字符串作为其参数(文件内容和要比较的每个字符串),然后返回一个处理后的字符串,该字符串将用于实际的比较。
例如,如果你想比较之前移除所有空白字符(空格、制表符、换行符),你可以使用以下示例中的函数。这在不关心文件内容格式的情况下非常有用。
$this->assertFileContains( 'namespace App\\Models; class User{ }', $userModelFilePath, function($str) { return str_replace([' ', "\t", "\n"], '', $str); } );
因为这个函数非常有用,我将其添加到了一个公共静态方法removeWhiteSpaces中,这样你就不必每次都自己编写它。你可以像这样使用它
assertFileContains($substr, $filePath, static::removeWhiteSpaces());
assertFileContentsEquals(string $expected, string $path, [callable $processor])
此断言与assertFileContains(...)类似,但只能接收单个字符串作为第一个参数,并将检查该字符串是否与文件的全部内容完全相同。也可以提供一个处理器函数/可调用项,就像前面的断言一样。
assertFilesExist(string | array $filePaths)
此断言与原始文件存在断言类似,但允许你提供一个或多个文件路径(字符串或数组),在失败的情况下,它将告诉你哪些文件不存在。
assertFoldersExist(string | array $folderPaths)
这与 assertDirectoryExists 类似,但断言有一个更好的名称 文件夹 而不是 目录(认真地说,谁会叫它们目录?)允许你提供一个或多个文件夹路径(字符串 | 数组),如果失败,它将告诉你哪些文件夹不存在。
列表 / 数组 / 集合
assertListsEqual($expected, $actual, [bool $strict = false])
此断言将尽力检查实际列表是否与预期列表相同。
$expected 和 $actual 参数可以是任何可迭代类型——因此术语列表是通用的。
- 数组
- 任何可迭代的对象(请参阅 php 文档)
- 实现 Illuminate\Contracts\Support 的对象(例如 Laravel 集合)
这会尝试比较关联列表(具有字符串键)、索引列表(具有数字键)以及混合列表(具有字符串和整数键),忽略索引项出现的顺序。
此断言还会比较深层/嵌套列表——这对于嵌套索引列表尤其具有挑战性。
要进行严格比较,将 $strict 标志设置为 true。请注意,NULL 值将单独比较,因此它们必须与另一个 NULL 值匹配,无论 $strict 如何,但任何其他东西,如布尔值及其数值对应物 0 和 1,在非严格模式下将进行交叉匹配,可能提供错误的断言。
目前有几个注意事项(它们可以解决,但有人需要它们吗?这值得努力吗?)
- 除了列表(集合/可迭代列表实例)和 Eloquent 模型(这是 Laravel 的事情)之外的对象无法正确比较
- 在严格模式下,对象必须是同一实例的引用(比较 spl_ids)
- 在非严格模式下,仅比较对象类
- 可调用项无法比较——只有实际列表包含相同数量的可调用项
- 资源无法比较——只有实际列表包含相同数量的资源
$this->assertListsEqual(['a', 1, [true, null, collect([0, 5])]], [[null, true, [5, 0]], 1, 'a']); //this will succeed in non-strict mode, but will fail in strict mode $this->assertListsEqual(['a', 1, [1, null, collect([0, 5])]], [[null, true, [5, false]], 1, 'a']);
assertArraysEqual($expected, $actual, [bool $strict = false])
这使用之前的(assertListEqual)断言,但检查两个列表是否实际是数组。
辅助工具
expectAssertionToFail(...$messages)
此辅助工具的工作方式类似于断言,并期望下一个(或下一个之一)断言失败。如果提供了消息或消息列表,它还会检查失败消息是否包含给定的字符串。
由于 PHPUnit 的工作方式,测试在第一个失败的断言后结束,因此你在失败断言之后编写的任何断言都将被忽略(有绕过方法,但这是一个很好的挑战你的创造力或 StackOverflow 搜索技能的机会)。话虽如此,建议在测试结束时使用此方法,在失败断言之前。
例如:
public function test_that_something_does_not_work() { //successful assertion $this->assertFoldersExist([__DIR__, app_path(), resource_path()]); //expect the next assertion to fail and the failure message to contain the 2 missing folder paths $this->expectAssertionToFail(app_path('random/folder'), resource_path('nix/da')); //failing assertion $this->assertFoldersExist([__DIR__, app_path('random/folder'), resource_path('nix/da')]); }
测试
目前:18 个测试,65 个断言。
此包经过彻底测试,运行顺利。
未来开发 / 贡献 / 支持
我计划在我为我的项目开发新断言后立即在这里添加它们。如果您喜欢这个包,您也可以查看我的其他开源包(大多是针对 Laravel 的)。
此包是开源的,因此欢迎任何贡献。如果您想做出改进、新功能或重大更改的贡献,请在投入任何工作之前联系我,并告诉我您的需求以及您计划做出的更改。