集成测试中的并行 PHPUnit 测试特征用法

随着运行完整的 PHPUnit 套件所需的时间增加,我们的团队开始怀疑是否有可能并行运行单元测试。最近我读了一篇关于Paraunit的文章,Sebastian Bergman也写了,他将在PHPUnit 3.7中添加并行性。

但是集成测试仍然存在问题,或者更一般地说,与DB交互的测试。为了保持一致性,测试DB必须在每次测试后重置并加载夹具。但在并行测试中,存在争用条件的问题,因为所有进程都使用相同的数据库

因此,为了能够并行运行集成测试,我们必须为每个进程分配自己的数据库。我想问一下,如果有人对如何解决这个问题有一些想法。也许在另一个 xUnit 实现中已经有针对此问题的已实现解决方案。

在我的团队中,我们使用MongoDB,因此一种解决方案是以编程方式为每个PHPUnit进程创建一个配置文件,并生成DB名称(用于此进程),并且通过该方法,我们可以将主TestDb克隆到这个临时进程中。但在我们开始实施这种方法之前,我想征求您对该主题的想法。setUp()


答案 1

这是一个很好的问题:准备并行单元测试将需要学习一些新的最佳实践,我怀疑其中一些会减慢我们的测试速度。

在最高层面上,建议是:尽可能避免使用数据库进行测试。抽象出与数据库的所有交互,然后模拟该类。但是您已经注意到您的问题是关于集成测试的,而这是不可能的。

使用PDO时,我通常使用sqlite::memory:每个测试都有自己的数据库。它是匿名的,并在测试结束时自动清理。(但是我注意到,当您的实际应用程序不使用sqlite时,这会带来一些问题:使用内存中的sqlite DB来加快单元测试速度时,建议避免DB deps。 )

使用没有内存中选项的数据库时,请使用随机名称创建数据库。如果并行化是在 PHPUnit 进程级别,非常粗略,则可以使用进程 pid。但这与随机名称相比没有真正的优势。(我知道PHP是单线程的,但也许将来我们会有一个自定义的phpUnit模块,它使用线程来并行运行测试;我们不妨为此做好准备。

如果你有一本 xUnit Test Patterns 的书,第 13 章是关于测试数据库的(相对较短)。关于瞬态与持久夹具的第8章和第9章也很有用。而且,当然,这本书的大部分内容都是关于抽象层的,以使模拟更容易:-)


答案 2

还有这个很棒的库(最快),用于并行执行测试。它针对功能/集成测试进行了优化,提供了一种并行处理N个数据库的简单方法。

我们的旧代码库在 30 分钟内运行,现在使用 4 个处理器在 7 分钟内运行。

特征

  • 功能测试可以使用环境变量为每个处理器使用一个数据库。
  • 默认情况下,测试是随机的。
  • 不与PhpUnit耦合,你可以运行任何命令。
  • 是用PHP开发的,没有依赖关系。
  • 作为输入,您可以使用phpunit.xml.dist文件或使用管道。
  • 包括 Behat 扩展,可轻松将方案输送到最快的速度。
  • 使用 -v 选项增加详细程度。

用法

find tests/ -name "*Test.php" | ./bin/fastest "bin/phpunit -c app {};"


推荐