ahj/approval-tests

dev-main 2021-04-06 15:27 UTC

This package is auto-updated.

Last update: 2024-09-06 22:55:38 UTC


README

GitHub Build Status Scrutinizer Code Quality Scrutinizer Code Coverage Approval Tests on packagist.org

批准测试

为什么使用批准测试

假设你有(可能是遗留的)代码,
并且你想要用回归测试来覆盖它,
并且你不想在单元测试中为每个输入指定输出,
并且你不想在更改逻辑后调整所有测试输出,
那么你应该使用批准测试。

安装

composer require ahj/approval-tests --dev

用法

/tests/Example 下找到一个如何进行批准测试的示例。

使用phpunit创建一个测试,指定你的逻辑的输入,将输出存储在变量中,并传递给
Approvals::create()->verifyList($input, $output):

public function testUpdateQuality(): void
{
    $input = [
        new Item('foo', 0, 1),
    ];

    $output = (new GildedRose())->updateQuality($input);

    Approvals::create()->verifyList($input, $output);
}

verifyList($input, $output) 将创建一个接收数据映射,并通过执行 Assert::assertEquals($approved, $received) 来与之前的数据版本进行比较。

然后运行phpunit

$ vendor/bin/phpunit tests

然后你将在你的测试目录中看到一个新目录,其中包含两个文件

/approval
  |__ approved.txt
  |__ received.txt

初始时 approved.txt 是空的。
received.txt 中,你会找到 $input 映射到 $output,例如

[foo, 0, 1] -> [foo, -1, 0]

通过将 received.txt 的内容复制到 approved.txt 或使用控制台命令来批准 $output

$ mv tests/Example/approval/received.txt tests/Example/approval/approved.txt

Screenshot 2021-03-27 at 09 46 18

当你再次运行测试时,received.txt 将消失,你将在 approval.txt 中有你的测试输出。接下来你只需在你的测试中添加更多 $input 数组案例并批准结果。无需手动指定任何输出 :)

选项

如果你的逻辑不需要输入,则将空数组作为 $input 传递

    Approvals::create()->verifyList([], $output);

received.txt 中,你将只显示 $output,例如

[foo, -1, 0]

$plain = true 作为 verifyList() 的第三个参数传递,以在 received.txt 中获得非格式化的输出

    Approvals::create()->verifyList([], $output, true);

根据 $output 的类型,received.txt 中将会有非格式化或json编码的字符串。对于对象或数组,它将是

{"dirPath":"bar","fileNumber":10,"randomList":[]},{"dirPath":"bar","fileNumber":100,"randomList":[]}

对于字符串,它将是

+--------------+-------------+--------+--------+------+-----+------------+---------+---------+---------+---------+---------+--------+-------+
| benchmark    | subject     | groups | params | revs | its | mem_peak   | best    | mean    | mode    | worst   | stdev   | rstdev | diff  |
+--------------+-------------+--------+--------+------+-----+------------+---------+---------+---------+---------+---------+--------+-------+
| HashingBench | benchMd5    |        | []     | 1000 | 10  | 1,255,792b | 0.931μs | 0.979μs | 0.957μs | 1.153μs | 0.062μs | 6.37%  | 1.00x |
| HashingBench | benchSha1   |        | []     | 1000 | 10  | 1,255,792b | 0.988μs | 1.015μs | 1.004μs | 1.079μs | 0.026μs | 2.57%  | 1.04x |
+--------------+-------------+--------+--------+------+-----+------------+---------+---------+---------+---------+---------+--------+-------+

测试组合

何时使用组合

如果你有一个函数,例如,它接受三个参数,并且你想要使用不同的值测试每个参数的行为,

复制以下代码或使用此存储库的 示例 并根据你的用例调整输入的数量和类型。在 $arguments 中指定你想要测试的方法的输入参数:要么在数组中明确列出参数可以取的值,要么使用 range()。然后将这些参数以及匿名函数传递给 CombinationApprovals::create()->verifyAllCombinations()

public function testUpdateQualityWithCombinations(): void
{
    $arguments = [
        ['foo', 'bar'], # values for $name
        range(0, 3),    # values for $sellIn
        [15, 20, 25],   # values for $quantity
    ];

    CombinationApprovals::create()->verifyAllCombinations(
        function (string $name, int $sellIn, int $quantity) {
            $items = [new Item($name, $sellIn, $quantity)];
    
            return (new GildedRose())->updateQuality($items);
        },
        $arguments
    );
}

匿名函数指定输入参数应该如何传递到你要测试的逻辑中。它还必须返回你测试逻辑的输出,以便 verifyAllCombinations() 可以将其写入 received.txt 并与最新的 approved.txt 进行比较。

对于上面的示例,批准工具将创建指定输入值的所有可能的组合,将这些映射到测试逻辑的相关输出,并将其按如下方式写入 received.txt

[bar, 3, 25] -> [bar, 2, 24]
[bar, 3, 20] -> [bar, 2, 19]
[bar, 3, 15] -> [bar, 2, 14]
[bar, 2, 25] -> [bar, 1, 24]
[bar, 2, 20] -> [bar, 1, 19]
[bar, 2, 15] -> [bar, 1, 14]
[bar, 1, 25] -> [bar, 0, 24]
[bar, 1, 20] -> [bar, 0, 19]
[bar, 1, 15] -> [bar, 0, 14]
[bar, 0, 25] -> [bar, -1, 23]
[bar, 0, 20] -> [bar, -1, 18]
[bar, 0, 15] -> [bar, -1, 13]
[foo, 3, 25] -> [foo, 2, 24]
[foo, 3, 20] -> [foo, 2, 19]
[foo, 3, 15] -> [foo, 2, 14]
[foo, 2, 25] -> [foo, 1, 24]
[foo, 2, 20] -> [foo, 1, 19]
[foo, 2, 15] -> [foo, 1, 14]
[foo, 1, 25] -> [foo, 0, 24]
[foo, 1, 20] -> [foo, 0, 19]
[foo, 1, 15] -> [foo, 0, 14]
[foo, 0, 25] -> [foo, -1, 23]
[foo, 0, 20] -> [foo, -1, 18]
[foo, 0, 15] -> [foo, -1, 13]

依赖