spatie/phpunit-snapshot-assertions

使用 PHPUnit 进行快照测试

5.1.6 2024-05-03 07:53 UTC

README

Latest Version on Packagist Software License run-tests Total Downloads

快照测试是一种无需编写实际测试用例的测试方法。

您可以在我们的 Testing Laravel 课程中的这个免费视频中了解更多信息:此视频。不要担心,您也可以在非 Laravel 项目中使用此包。

use Spatie\Snapshots\MatchesSnapshots;

class OrderTest
{
    use MatchesSnapshots;

    public function test_it_casts_to_json()
    {
        $order = new Order(1);

        $this->assertMatchesJsonSnapshot($order->toJson());
    }
}

第一次运行时,测试运行器将创建一个新的快照。

> ./vendor/bin/phpunit

There was 1 incomplete test:

1) OrderTest::test_it_casts_to_json
Snapshot created for OrderTest__test_it_casts_to_json__1

OK, but incomplete, skipped, or risky tests!
Tests: 1, Assertions: 0, Incomplete: 1.

在随后的运行中,只要快照没有变化,测试就会通过。

> ./vendor/bin/phpunit

OK (1 test, 1 assertion)

如果有回归,测试会失败!

$orderId = new Order(2); // Regression! Was `1`
> ./vendor/bin/phpunit

1) OrderTest::test_it_casts_to_json
Failed asserting that two strings are equal.
--- Expected
+++ Actual
@@ @@
Failed asserting that '{"id":2}' matches JSON string "{
    "id": 1
}

FAILURES!
Tests: 1, Assertions: 1, Failures: 1.

支持我们

我们投入了大量资源来创建 一流的开放源代码包。您可以通过 购买我们的付费产品之一 来支持我们。

我们非常感谢您从家乡寄给我们明信片,说明您正在使用我们哪些包。您可以在 我们的联系页面 上找到我们的地址。我们将把所有收到的明信片发布在我们的 虚拟明信片墙上

安装

您可以通过 composer 安装此包

composer require --dev spatie/phpunit-snapshot-assertions

用法

要创建快照断言,请在使用测试用例类中使用 Spatie\Snapshots\MatchesSnapshots 特性。这将为类添加一系列断言方法

  • assertMatchesSnapshot($actual)
  • assertMatchesFileHashSnapshot($actual)
  • assertMatchesFileSnapshot($actual)
  • assertMatchesHtmlSnapshot($actual)
  • assertMatchesJsonSnapshot($actual)
  • assertMatchesObjectSnapshot($actual)
  • assertMatchesTextSnapshot($actual)
  • assertMatchesXmlSnapshot($actual)
  • assertMatchesYamlSnapshot($actual)
  • assertMatchesImageSnapshot($actual)

快照测试 101

让我们为一个简单的字符串 "foo" 进行快照断言。

public function test_it_is_foo() {
    $this->assertMatchesSnapshot('foo');
}

第一次运行断言时,没有快照可以与字符串进行比较。测试运行器生成一个新的快照并将测试标记为不完整。

> ./vendor/bin/phpunit

There was 1 incomplete test:

1) ExampleTest::test_it_matches_a_string
Snapshot created for ExampleTest__test_it_matches_a_string__1

OK, but incomplete, skipped, or risky tests!
Tests: 1, Assertions: 0, Incomplete: 1.

快照 ID 根据测试和测试用例的名称生成。基本快照返回实际值的纯文本或 YAML 表示形式。

foo

让我们重新运行测试。测试运行器将看到已经有一个快照用于断言并执行比较。

> ./vendor/bin/phpunit

OK (1 test, 1 assertion)

如果我们将实际值更改为 "bar",测试将失败,因为快照仍然返回 "foo"。

public function test_it_is_foo() {
    $this->assertMatchesSnapshot('bar');
}
> ./vendor/bin/phpunit

1) ExampleTest::test_it_matches_a_string
Failed asserting that two strings are equal.
--- Expected
+++ Actual
@@ @@
-'foo'
+'bar'

FAILURES!
Tests: 1, Assertions: 1, Failures: 1.

当我们期望一个更改的值时,我们需要告诉测试运行器更新现有的快照而不是使测试失败。这可以通过在 phpunit 命令中添加 -d --update-snapshots 标志或设置 UPDATE_SNAPSHOTS 环境变量为 true 来实现。

> ./vendor/bin/phpunit -d --update-snapshots

OK (1 test, 1 assertion)

结果,我们的快照文件返回 "bar" 而不是 "foo"。

bar

文件快照

“MatchesSnapshots” 特性提供了两种方法来断言文件与第一次运行测试时创建的快照相同

“assertMatchesFileHashSnapshot($filePath)” 断言断言传入函数的文件哈希与快照中保存的哈希匹配。这种断言非常快,使用的磁盘空间非常少。这种断言的缺点是,如果测试失败,没有简单的方法可以查看两个文件之间的差异。

assertMatchesFileSnapshot($filePath) 断言几乎与文件哈希断言相同,不同的是它实际上会将整个文件保存到快照目录中。如果断言失败,它会将失败的文件放在快照文件旁边,以便可以轻松手动比较。测试通过时,持久化的失败文件将自动删除。此断言在处理需要手动比较的二进制文件(如图像或PDF)时非常有用。

图像快照

assertImageSnapshot 需要安装 spatie/pixelmatch-php 包。

如果给定的图像与第一次运行测试时制作的快照几乎相同,则此断言将通过。您可以通过传递断言的第二个参数来自定义阈值。较高的值将使比较更敏感。阈值应在0到1之间。

$this->assertMatchesImageSnapshot($imagePath, 0.1);

自定义快照ID和目录

快照ID是通过在 MatchesSnapshot 特性上的 getSnapshotId 方法生成的。通过覆盖此方法来自定义ID。默认情况下,快照ID由测试名称、测试用例名称和一个递增值组成,例如 Test__my_test_case__1

示例:将 __ 分隔符替换为 --

protected function getSnapshotId(): string
{
    return (new ReflectionClass($this))->getShortName().'--'.
        $this->name().'--'.
        $this->snapshotIncrementor;
}

默认情况下,快照存储在与测试类相对的 __snapshots__ 目录中。可以通过覆盖 getSnapshotDirectory 方法来更改此。

示例:将 __snapshots__ 目录重命名为 snapshots

protected function getSnapshotDirectory(): string
{
    return dirname((new ReflectionClass($this))->getFileName()).
        DIRECTORY_SEPARATOR.
        'snapshots';
}

使用特定驱动程序

可以使用 assertMatchesSnapshot 方法的第二个参数指定用于序列化数据的应用程序,以便您可以选择更适合您需求的选项。

use Spatie\Snapshots\Drivers\JsonDriver;
use Spatie\Snapshots\MatchesSnapshots;

class OrderTest
{
    use MatchesSnapshots;

    public function test_snapshot_with_json_driver()
    {
        $order = new Order(1);

        $this->assertMatchesSnapshot($order->toJson(), new JsonDriver());
    }
}

编写自定义驱动程序

驱动程序确保不同类型的数据可以以它们自己的方式序列化和匹配。驱动程序是一个实现 Spatie\Snapshots\Driver 接口的类,它需要实现三个方法: serializeextensionmatch

让我们快速看一下 JsonDriver

namespace Spatie\Snapshots\Drivers;

use PHPUnit\Framework\Assert;
use Spatie\Snapshots\Driver;
use Spatie\Snapshots\Exceptions\CantBeSerialized;

class JsonDriver implements Driver
{
    public function serialize($data): string
    {
        if (! is_string($data)) {
            throw new CantBeSerialized('Only strings can be serialized to json');
        }

        return json_encode(json_decode($data), JSON_PRETTY_PRINT).PHP_EOL;
    }

    public function extension(): string
    {
        return 'json';
    }

    public function match($expected, $actual)
    {
        Assert::assertJsonStringEqualsJsonString($actual, $expected);
    }
}
  • serialize 方法返回一个字符串,该字符串将被写入快照文件。在 JsonDriver 中,我们将解码并重新编码JSON字符串,以确保快照具有格式化打印。
  • 我们想将JSON快照保存为JSON文件,所以我们将使用 json 作为它们的文件扩展名。
  • 当匹配预期的数据与实际数据时,我们想使用PHPUnit内置的JSON断言,因此我们将调用特定的 assertJsonStringEqualsJsonString 方法。

可以通过将它们作为 assertMatchesSnapshot 的第二个参数传递来使用驱动程序。

$this->assertMatchesSnapshot($something->toYaml(), new MyYamlDriver());

在CI中的使用

在持续集成中运行测试时,您可能希望禁用快照的创建。

通过使用 --without-creating-snapshots 参数或将 CREATE_SNAPSHOTS 环境变量设置为 false,PHPUnit将在快照不存在时失败。

> ./vendor/bin/phpunit -d --without-creating-snapshots

1) ExampleTest::test_it_matches_a_string
Snapshot "ExampleTest__test_it_matches_a_string__1.txt" does not exist.
You can automatically create it by removing the `CREATE_SNAPSHOTS=false` env var, or `-d --no-create-snapshots` of PHPUnit's CLI arguments.

与并行测试一起使用

如果您想使用Paratest之类的工具或Laravel的 php artisan test --parallel 命令并行运行测试,您将必须使用环境变量。

> CREATE_SNAPSHOTS=false php artisan test --parallel

1) ExampleTest::test_it_matches_a_string
Snapshot "ExampleTest__test_it_matches_a_string__1.txt" does not exist.
You can automatically create it by removing the `CREATE_SNAPSHOTS=false` env var, or `-d --no-create-snapshots` of PHPUnit's CLI arguments.

Windows用户注意事项

Windows用户应在 .gitattributes 中配置他们的行结束。

# Snapshots used in tests hold serialized data and their line ending should be left unchanged
tests/**/__snapshots__/** binary

更新日志

有关最近更改的更多信息,请参阅 CHANGELOG

测试

composer test

贡献

有关详细信息,请参阅 CONTRIBUTING

安全性

如果您发现有关安全性的错误,请通过 [email protected] 发送电子邮件,而不是使用问题跟踪器。

明信片软件

您可自由使用本软件包,但如果它进入了您的生产环境,我们非常感谢您从家乡寄给我们一张明信片,并注明您正在使用我们的哪些软件包。

我们的地址是:Spatie,Kruikstraat 22,2018 安特卫普,比利时。

我们将在公司的网站上发布收到的所有明信片[链接]

致谢

许可证

MIT 许可证(MIT)。有关更多信息,请参阅许可证文件