brianium/paratest

PHP的并行测试

资助包维护!
Slamdunk
Paypal

安装次数: 57,423,137

依赖关系: 660

建议者: 28

安全性: 0

星星: 2,298

关注者: 41

分支: 227

开放问题: 6

v7.5.5 2024-09-20 12:57 UTC

README

Latest Stable Version Downloads Integrate Infection MSI

ParaTest的目标是支持PHPUnit的并行测试。只要你写好了PHPUnit测试,你就可以将paratest添加到你的项目中,并开始使用,无需额外的引导或配置!

优点

  • 零配置。安装后,使用vendor/bin/paratest通过TestCase并行化,或使用vendor/bin/paratest --functional通过Test并行化。就这么简单!
  • 代码覆盖率报告合并。运行N个并行进程中的测试,所有的代码覆盖率输出将合并为一个报告。

安装

使用Composer安装,请运行以下命令

composer require --dev brianium/paratest

版本

仅支持最新版本的PHPUnit,因此ParaTest也只积极维护最新版本。

这是因为以下原因

  1. 为了减少错误、代码重复与PHPUnit的不兼容性,从版本5开始,ParaTest大量依赖于PHPUnit @internal
  2. PHP和PHPUnit近年来发展迅速,增加了太多的维护负担,我们只能承担最新的版本以保持其更新

用法

安装后,二进制文件可在vendor/bin/paratest找到。使用--help选项运行它,以查看所有可用选项的完整列表。

测试令牌

TEST_TOKEN环境变量保证具有一个与其他当前运行测试不同的值。这对于例如为每个测试使用不同的数据库非常有用

if (getenv('TEST_TOKEN') !== false) {  // Using ParaTest
    $dbname = 'testdb_' . getenv('TEST_TOKEN');
} else {
    $dbname = 'testdb';
}

还有一个可用的UNIQUE_TEST_TOKEN环境变量,保证其值对于每次运行和每个进程都是唯一的。

代码覆盖率

ParaTest总是在执行测试套件之前预热缓存。

PCOV

如果你已经安装了pcov,但需要在运行测试时启用它,你必须通过所需的PHP二进制选项传递

php -d pcov.enabled=1 vendor/bin/paratest --passthru-php="'-d' 'pcov.enabled=1'"

xDebug

如果你已经安装了xDebug,通过环境变量激活它就足够了,即使在子进程中也可以运行

XDEBUG_MODE=coverage vendor/bin/paratest

所有测试的初始设置

由于ParaTest在并行测试中运行多个进程,每个进程都有自己的PHP解释器实例,因此执行初始化步骤一次的技术与PHPUnit不同。以下模式不会按预期工作 - 只运行一次初始化 - 而是每个进程运行一次初始化

private static bool $initialized = false;

public function setUp(): void
{
    if (! self::$initialized) {
         self::initialize();
         self::$initialized = true;
    }
}

这是因为静态变量在单个进程的执行过程中持续存在。在并行测试中,每个进程都有自己独立的$initialized实例。你可以使用以下模式来确保你的初始化在整个测试调用中只运行一次

static bool $initialized = false;

public function setUp(): void
{
    if (! self::$initialized) {
        // We utilize the filesystem as shared mutable state to coordinate between processes
        touch('/tmp/test-initialization-lock-file');
        $lockFile = fopen('/tmp/test-initialization-lock-file', 'r');

        // Attempt to get an exclusive lock - first process wins
        if (flock($lockFile, LOCK_EX | LOCK_NB)) {
            // Since we are the single process that has an exclusive lock, we run the initialization
            self::initialize();
        } else {
            // If no exclusive lock is available, block until the first process is done with initialization
            flock($lockFile, LOCK_SH);
        }

        self::$initialized = true;
    }
}

故障排除

如果你遇到paratest的问题,请尝试通过启用调试输出通过--verbose --debug来获取更多关于问题的信息。

当子进程失败时,输出中会给出原始命令,然后可以在终端中复制粘贴以运行和调试。所有内部命令都使用--printer [...]\NullPhpunitPrinter运行,这会静默原始PHPUnit输出:在调试运行期间,删除该选项以恢复输出并查看PHPUnit正在做什么。

注意事项

  1. 常量、静态方法、静态变量以及被其他测试类消耗的测试类暴露的所有内容(包括反射)均不受支持。这是由于当前WrapperRunner实现以及PHPUnit搜索类的限制。修复方法是将在测试类之外的其他类中放置共享代码。

与PHPStorm集成

ParaTest提供了一个专门的二进制文件与PHPStorm一起使用;按照以下步骤在PHPStorm中使ParaTest工作:

  1. 请确保您已经在PHPStorm中配置了PHPUnit:[链接](https://www.jetbrains.com/help/phpstorm/using-phpunit-framework.html#php_test_frameworks_phpunit_integrate)
  2. 转到“运行” -> “编辑配置...

  3. 选择“添加新配置”,选择“PHPUnit”类型并将其命名为“ParaTest”
  4. 在“命令行” -> “解释器选项”中添加./vendor/bin/paratest_for_phpstorm
  5. 您想要传递给ParaTest的任何附加选项应放在“测试运行器” -> “测试运行器选项”部分

现在,您应该在配置列表中有一个“ParaTest”运行。它应该可以与“运行”覆盖中的“重新运行失败的测试”和“切换自动测试”按钮本地产生交互。

运行时带覆盖率

要使用可用的覆盖率引擎之一进行覆盖率,必须已在PHPStorm中配置并启用,以便辅助二进制文件可以正确处理代码覆盖率

对于贡献者:测试ParaTest本身

在创建拉取请求之前,请确保使用make命令运行所有必要的检查。