phpunit - 测试非常慢

2022-08-30 10:54:46

我正在深入研究单元测试的世界。

我遇到的一个问题,也是我想要反馈的地方,是当一个人运行多个测试套件时,也许只是我,但我需要使用参数 --process-isolation 来通过我的测试。我可以单独运行我的任何套件而不会出现问题,但是如果我没有--进程隔离的情况下运行我迄今为止拥有的6-7个套件,并且在它们之间分布了180个断言,那么运行它们将失败。问题是,使用此参数会使测试运行持续 35 分钟,而通常为 2.5 分钟。那是一种哄的等待。

该问题与将模拟的 DI 容器用于特定测试有关,并且当测试套件以链接方式运行时,容器未正确重新初始化。在 DI 容器上设置的静态属性用于测试预期故障会使以下套件中的测试失败。容器有一个参数,可以将包含的对象保存在静态 var 中,以便在每次调用时返回相同的实例。伪装的单例。这在应用程序级别运行良好,只是测试的麻烦。

我可以避免使用容器参数,并对应用程序进行编码以不使用静态属性,但是为了方法而避免使用有用的语言构造似乎有些过分。

也许我做错了什么(我当然希望如此!)但我的印象是,如果有人想在每次测试中都以干净的状态运行SUT测试,那么使用--进程隔离就没有绕过去了。这使得测试非常耗时,并带走了一点乐趣。我在编码时通过单独运行套件和测试,并在主要提交之前在后台运行套件,在某种程度上绕过了这个问题。

我正在经历的事情是否正常,有没有办法解决这个问题?你们的测试人员如何确保测试时间是合理的?如何处理静态数据,以免影响测试?

任何见解赞赏/评论赞赏。


答案 1

您有几个问题。

首先是进程隔离。通常,它不应该是必要的,你只想用它来找出哪个特定的测试是致命地破坏你的测试的测试。正如你自己所指出的,它非常慢,这是你无法解决的问题。但是,您可能希望禁用备份全局 var,这样可以为每个测试节省一些毫秒。

第二个问题,导致你的第一个问题,是你的代码是不可测试的,因为在测试期间保留了静态vars - 我最讨厌的单例问题。可以通过在依赖项容器中提供“清理”或“重置”方法来解决此问题。这些将从主测试用例类中的方法调用,并将所有内容重置为干净状态。setUp()

速度

关于测试的运行时 - 我最近写了一篇关于找出哪些测试太慢的博客文章。通常,如果在保存文件或每个提交到自己的框中后无法运行测试,则测试速度太慢。10秒对我来说几乎是不能接受的。您拥有的测试越多,运行速度就越慢。

如果您确实有 35 分钟的时间,请将测试拆分为合理的组,以便您可以在自己的计算机上运行必要的测试 - 仅测试您更改的代码的测试。Pyrus是下一代PEAR安装程序,具有漂亮的功能,可以自动检测并运行需要运行的测试,具体取决于您更改的文件。PHPUnit没有,但你可以手动模拟它,:)phpunit --group ..

始终注意模拟 Web 服务和数据库,或者至少运行数据库,仅包含每个测试所需的数据。在验证是否可以将用户保存到数据库的测试中等待 3 秒的 Web 服务响应是你永远想要的。


答案 2

当我使用MySQL而不是SQLite进行测试时,我通常会做的一件事就是像这样在Trait内部添加。我体验到这将使测试,特别是使用MySQL的测试速度更快::memory:Hash::setRounds(5);tests/CreatesApplication.php

public function createApplication()
{
    $app = require __DIR__ . '/../bootstrap/app.php';

    $app->make(Kernel::class)->bootstrap();

    // TODO: DON'T FORGET TO IMPORT HASH OBJECT ON TOP
    Hash::setRounds(5);

    return $app;
}

推荐