bmarsaud/phpunit-snapshot-assertions

使用PHPUnit进行快照测试

4.2.2 2020-10-10 21:11 UTC

README

Latest Version on Packagist Software License GitHub Tests Action Status Quality Score StyleCI Total Downloads

为什么要有这个分支?

这个分支的目的是使spatie/phpunit-snapshot-assertions包与PHP 7.3兼容。

兼容性是通过使用Rector来保证的。

注意,目前可用的唯一版本是4.2.2

一个更持久和可靠的方法是在原始存储库的每个标签推送时应用Rector的GitHub操作。

描述

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

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.

支持我们

通过观看我们的高级视频课程,了解如何创建此类包

Laravel Package training

我们在创建最好的开源包上投入了大量的资源。您可以通过购买我们的付费产品之一来支持我们。

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

安装

您可以通过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)

快照测试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标志来实现。

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

OK (1 test, 1 assertion)

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

bar

文件快照

MatchesSnapshots特质提供了两种方式来断言文件与第一次运行测试时制作的快照完全相同

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

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

自定义快照ID和目录

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

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

protected function getSnapshotId(): string
{
    return (new ReflectionClass($this))->getShortName().'--'.
        $this->getName().'--'.
        $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参数,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 `-d --no-create-snapshots` of PHPUnit's CLI arguments.

给Windows用户的一封信

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

tests/**/__snapshots__/** text eol=lf

更改日志

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

测试

composer test

贡献

有关详细信息,请参阅CONTRIBUTING

安全

如果您发现任何与安全相关的问题,请通过电子邮件freek@spatie.be发送,而不是使用问题跟踪器。

贺卡软件

您可以使用此软件包,但如果它进入您的生产环境,我们非常感谢您从您家乡寄给我们一张明信片,说明您正在使用我们的哪个包。

我们的地址是:Spatie,Samberstraat 69D,2060 安特卫普,比利时。

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

致谢

许可证

MIT许可证(MIT)。请参阅许可证文件获取更多信息。