irl/paratest

PHP 的并行测试 | 为 IRL 实现而分支

dev-master 2020-07-22 14:17 UTC

This package is not auto-updated.

Last update: 2024-09-27 08:58:38 UTC


README

Integrate Packagist

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

优点

为什么要在现有的并行测试运行程序中选择 paratest 而不是其他选择呢?

  • 代码覆盖率报告合并。 在 N 个并行进程中运行测试,所有的代码覆盖率输出将合并成一个报告。
  • 零配置。 安装 composer 后,运行 vendor/bin/paratest -p4 path/to/tests。就这样!
  • 灵活。 在单独的进程中隔离测试文件,或者利用 WrapperRunner 实现更快地运行。

安装

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

composer require --dev brianium/paratest

版本

用法

安装后,二进制文件可以在 vendor/bin/paratest 下找到。用法如下

Usage:
 paratest [-p|--processes PROCESSES] [-f|--functional] [--no-test-tokens] [-h|--help] [--coverage-clover COVERAGE-CLOVER] [--coverage-crap4j COVERAGE-CRAP4J] [--coverage-html COVERAGE-HTML] [--coverage-php COVERAGE-PHP] [--coverage-text] [--coverage-xml COVERAGE-XML] [-m|--max-batch-size MAX-BATCH-SIZE] [--filter FILTER] [--parallel-suite] [--passthru PASSTHRU] [--passthru-php PASSTHRU-PHP] [-v|--verbose VERBOSE] [--whitelist WHITELIST] [--phpunit PHPUNIT] [--runner RUNNER] [--bootstrap BOOTSTRAP] [-c|--configuration CONFIGURATION] [-g|--group GROUP] [--exclude-group EXCLUDE-GROUP] [--stop-on-failure] [--log-junit LOG-JUNIT] [--colors] [--testsuite [TESTSUITE]] [--path PATH] [--] [<path>]

Arguments:
 path                        The path to a directory or file containing tests. (default: current directory)
      
Options:      
 --processes (-p)            The number of test processes to run. (Default: auto)
                             Possible values:
                             - Integer (>= 1): Number of processes to run.
                             - auto (default): Number of processes is automatically set to the number of logical CPU cores.
                             - half: Number of processes is automatically set to half the number of logical CPU cores.
 --functional (-f)           Run test methods instead of classes in separate processes.
 --no-test-tokens            Disable TEST_TOKEN environment variables. (Default: Variable is set)
 --help (-h)                 Display this help message.
 --coverage-clover           Generate code coverage report in Clover XML format.
 --coverage-crap4j           Generate code coverage report in Crap4J XML format.
 --coverage-html             Generate code coverage report in HTML format.
 --coverage-php              Serialize PHP_CodeCoverage object to file.
 --coverage-text             Generate code coverage report in text format.
 --coverage-xml              Generate code coverage report in PHPUnit XML format.
 --max-batch-size (-m)       Max batch size (only for functional mode). (Default: 0)
 --filter                    Filter (only for functional mode).
 --phpunit                   The PHPUnit binary to execute. (Default: vendor/bin/phpunit)
 --runner                    Runner, WrapperRunner or SqliteRunner. (Default: Runner)
 --bootstrap                 The bootstrap file to be used by PHPUnit.
 --configuration (-c)        The PHPUnit configuration file to use.
 --group (-g)                Only runs tests from the specified group(s).
 --exclude-group             Don't run tests from the specified group(s).
 --stop-on-failure           Don't start any more processes after a failure.
 --log-junit                 Log test execution in JUnit XML format to file.
 --colors                    Displays a colored bar as a test result.
 --testsuite                 Filter which testsuite to run. Run multiple suits by separating them with ",". Example:  --testsuite suite1,suite2
 --path                      An alias for the path argument.
 --parallel-suite            Run testsuites in parallel as opposed to running test classes / test functions in parallel.
 --passthru=PASSTHRU         Pass the given arguments verbatim to the underlying test framework. Example: --passthru="'--prepend' 'xdebug-filter.php'"
 --passthru-php=PASSTHRU-PHP Pass the given arguments verbatim to the underlying php process. Example: --passthru-php="'-d' 'zend_extension=xdebug.so'"
  -v, --verbose=VERBOSE      If given, debug output is printed. Example: --verbose=1
 

优化速度

要充分发挥 paratest 的作用,你必须仔细调整参数。

  1. 使用 -p 调整进程数量

    为了充分利用你的 CPU 核心,你应该至少有一个进程对应一个核心。更多的进程允许更好的资源利用,但请注意,每个进程都有自己的启动成本。默认值为自动,这意味着逻辑 CPU 核心的数量被设置为进程数量。你可能尝试像逻辑 CPU 核心数 * 2(例如,如果你有 8 个逻辑核心,你可能尝试 16),但请注意,每个进程都会产生一点开销。

  2. 使用 -f 选择按测试用例或按测试方法并行化

    如果你有很少的测试用例(类)但有多个运行时间长的测试方法,你应该使用 -f 选项来启用 功能模式 并允许同一类的不同方法并行执行。请注意,默认值为按测试用例并行化,以解决测试方法之间的依赖关系。请注意,在大多数项目中,使用 -f更慢的,因为每个测试 方法 都需要单独引导。

  3. 如果可能的话,使用 WrapperRunner 或 SqliteRunner

    PHPUnit 默认的 Runner 为每个测试用例(或功能模式中的方法)启动一个新的进程。这提供了最高的兼容性,但伴随着许多启动进程和每个进程的引导成本。特别是当你有缓慢的引导(如数据库设置)时,你应该尝试使用 --runner WrapperRunner 的 WrapperRunner 或使用 --runner SqliteRunner 的 SqliteRunner。它为每个并行进程(-p)启动一个“工作”进程,执行一次引导并重复使用这些进程执行每个测试。这样,进程启动和引导的开销就降到最低。

  4. 调整批处理最大大小 --max-batch-size

    批量大小将影响用于单个测试方法的原子测试的最大数量。如果没有方法提供数据提供者,一个原子测试将是一个测试类中的一个测试方法,或者是一个数据集中的单个条目。增加这个值可以减少每个进程的开销,在大多数情况下也会降低并行效率。减少这个值可以增加每个进程的开销,在大多数情况下也会提高并行效率。如果所有测试的总数小于最大批量大小,则所有内容将在一个进程线程中处理,因此在这种情况下 paratest 完全无用。找到最有效的批量大小的方法是使用不同的批量大小值进行测试,并选择最佳。最大批量大小为 0 表示不使用批量分组,一个批量将等于所有方法测试(一个或所有来自数据提供者)。最大批量大小为 1 表示每个批量只包含来自数据提供者的一个测试,如果没有使用数据提供者,则是一个方法。较大的最大批量大小可能会显著增加 phpunit 命令行长度,从而导致进程失败。减少最大批量大小以缩短命令行长度。Windows 的限制约为 32k,Linux - 2048k,Mac OS X - 256k。

示例

示例假设您的测试位于 ./test/unit 下。

# Run all unit tests in 8 parallel processes
vendor/bin/paratest -p8 test/unit
# Run all unit tests in 4 parallel processes with WrapperRunner and output html code coverage report to /tmp/coverage
# (Code coverage requires Xdebug to be installed)
vendor/bin/paratest -p4 --runner=WrapperRunner --coverage-html=/tmp/coverage test/unit

故障排除

如果您遇到与 paratest 相关的问题,请通过启用调试输出(--verbose=1)来尝试获取有关问题的更多信息。

如果您使用的是 WrapperRunner 进行执行,请考虑通过 export PT_LOGGING_ENABLE="true" 启用日志记录以进行故障排除。相应的日志文件位于您的 sys_get_temp_dir()

有关更多信息,请参阅 日志记录文档

生成代码覆盖率

示例假设您的测试位于 ./test/unit 下。

vendor/bin/paratest -p 1 --coverage-text test/unit

Running phpunit in 1 process with /codebase/paratest/vendor/phpunit/phpunit/phpunit

Configuration read from /codebase/paratest/phpunit.xml.dist

...............................................................  63 / 155 ( 40%)
............................................................... 126 / 157 ( 80%)
.....................................

Time: 27.2 seconds, Memory: 8.00MB

OK (163 tests, 328 assertions)


Code Coverage Report:
  2019-01-25 09:41:26

 Summary:
  Classes: 22.86% (8/35)
  Methods: 49.47% (139/281)
  Lines:   59.38% (896/1509)

注意:生成覆盖率本身就是一个艺术。请参阅我们关于如何正确设置 paratest 生成代码覆盖率 的全面指南。

Windows

Windows 用户请确保使用适当的批处理文件。

例如

vendor\bin\paratest.bat --phpunit vendor\bin\phpunit.bat ...

ParaTest 假设使用 PSR-0 加载测试。

为了方便,ParaTest 的 Windows 版本使用 79 列模式,以防止在标准的 80x25 Windows 控制台中出现空白行。

PHPUnit Xml 配置支持

当运行 PHPUnit 测试时,ParaTest 将自动通过 --configuration 开关将 phpunit.xml 或 phpunit.xml.dist 传递给 phpunit 运行器。ParaTest 还允许手动指定配置路径。

ParaTest 将依赖于 phpunit 的 xml 配置的 testsuites 节来处理加载套件。

以下 phpunit 配置文件用于 ParaTest 的测试用例。

<?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="false"
         backupStaticAttributes="false"
         bootstrap="../bootstrap.php"
         colors="true"
         convertErrorsToExceptions="true"
         convertNoticesToExceptions="true"
         convertWarningsToExceptions="true"
         processIsolation="false"
         stopOnFailure="false"
         syntaxCheck="false"
        >
    <testsuites>
        <testsuite name="ParaTest Fixtures">
            <directory>./tests/</directory>
        </testsuite>
    </testsuites>
</phpunit>

测试令牌

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

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

对于贡献者:测试 paratest 本身

ParaTest 的测试套件依赖于通过 composer 安装的 PHPUnit。确保在克隆后运行 composer install

请注意,必须将 php.ini 中的 display_errors 指令设置为 stderr 才能运行测试套件。

您可以使用 composer 脚本来方便地访问代码风格检查和测试。运行 compose run-script -l 以列出可用的命令。

composer run-script -l
scripts:
  style            Run style checks (only dry run - no fixing!)
  style-fix        Run style checks and fix violations
  static-analysis  Run static analysis
  test             Run all tests
  test-unit        Run only unit tests
  test-functional  Run only functional tests
  test-paratest    Run all tests with paratest itself

运行单元测试:composer test-unitvendor/bin/phpunit test/unit

运行功能测试:composer test-functionalvendor/bin/phpunit test/functional

您可以通过在项目目录中运行 phpunit 来一次性运行所有测试:composer testvendor/bin/phpunit

ParaTest 可以通过从 bin 目录运行来运行其自身的测试套件:composer testbin/paratest

静态分析代码:composer static-analysis

在创建Pull Request之前,请务必运行样式检查并提交最终更改: composer style-fix

使用composer style仅显示违规而不会进行修复。

要查看ParaTest的实际应用示例,请查看示例