liuggio/fastest

简单的并行测试执行...附带一些功能测试的便利功能。

v1.12.0 2024-03-15 09:20 UTC

README

example branch parameter Latest Stable Version Latest Unstable Version

仅有一件事

执行并行命令,为每个处理器创建一个进程(附带一些功能测试的便利功能)。

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

Fastest 可以与任何可用的测试工具一起使用!它只是并行执行它。

它针对功能测试进行了优化,提供了一种轻松地并行工作与 N 个数据库的方法。

座右铭

"我遇到了一个问题,
所以我决定使用线程。
tNwoowp rIo bhlaevmes。

为什么

我们厌倦了无法在我们的项目(一个大型的复杂功能项目)中使用 paratest
Parallel 是一个伟大的工具,但不适合功能测试。
没有简单的工具可用于功能测试。

我们旧代码库的运行时间为 30 分钟,现在在 4 个处理器的情况下为 7 分钟。

功能

  1. 功能测试可以使用环境变量为每个处理器使用一个数据库。
  2. 默认情况下测试是随机化的。
  3. 它不与 PhpUnit 绑定,可以运行任何命令。
  4. 它是在没有依赖的情况下用 PHP 开发的。
  5. 输入可以使用 phpunit.xml.dist 文件或使用管道(见下文)。
  6. 包括 Behat 扩展,可以轻松地将场景管道化到 fastest。
  7. 使用 -v 选项增加详尽程度。
  8. 可以在项目或全局模式下工作

如何

它创建了 N 个线程,其中 N 是计算机核心的数量。
真的很快,100% 用 PHP 编写,受 Parallel 启发。

用法

配置二进制文件的路径

以下示例使用安装在 vendor/ 目录的二进制文件路径。您可以通过定义 bin-dir 参数的 Composerbin/ 目录中使用符号链接

composer config "bin-dir" "bin"

然后您将能够调用 bin/ 目录中的二进制文件

  • bin/fastest 而不是 vendor/liuggio/fastest/fastest
  • bin/phpunit 而不是 vendor/phpunit/phpunit/phpunit

并行化一切

ls | ./fastest "echo slow operation on {}" -vvv

使用占位符

{} 是当前的测试文件。
{p} 是当前的处理器编号。
{n} 是当前测试的唯一编号。 phpunit {} 被用作默认命令。

PHPUnit

A. 使用 ls,列表文件夹作为输入 建议

ls -d test/* | ./vendor/liuggio/fastest/fastest "vendor/phpunit/phpunit/phpunit {};"

B. 使用 find,列表 PHP 文件作为输入

find tests/ -name "*Test.php" | ./vendor/liuggio/fastest/fastest  "vendor/phpunit/phpunit/phpunit {};"

C. 使用 phpunit.xml.dist 作为输入

您可以使用 -x 选项并从 phpunit.xml.dist 导入测试套件

./vendor/liuggio/fastest/fastest -x phpunit.xml.dist "vendor/phpunit/phpunit/phpunit {};"

如果您使用此选项,请确保测试套件包含大量目录: 此功能应得到改进,请不要责怪帮助。

功能测试和数据库

在您的测试中,您可以使用环境变量,
如果您在具有 4 个核心的计算机上运行测试,fastest 将并行创建 4 个线程,并且您可以在测试中更好地使用这些变量来识别当前进程

echo getenv('ENV_TEST_CHANNEL');          // The number of the current channel that is using the current test eg.2
echo getenv('ENV_TEST_CHANNEL_READABLE'); // Name used to make the database name unique, is a readable name eg. test_2
echo getenv('ENV_TEST_CHANNELS_NUMBER');  // Max channel number on a system (the core number) eg. 4
echo getenv('ENV_TEST_ARGUMENT');         // The current running test eg. tests/UserFunctionalTest.php
echo getenv('ENV_TEST_INC_NUMBER');       // Unique number of the current test eg. 32
echo getenv('ENV_TEST_IS_FIRST_ON_CHANNEL'); // Is 1 if is the first test on its thread useful for clear cache.

before 中设置数据库

您还可以在每个进程 before 测试时运行一个脚本,这对于初始化模式和加载固定值非常有用。

find tests/ -name "*Test.php" | ./vendor/liuggio/fastest/fastest -b"app/console doc:sch:create -e test" "vendor/phpunit/phpunit/phpunit {};";

生成和合并代码覆盖率

# Install phpcov in order to merge the code coverage
composer require --dev phpunit/phpcov
# Create a directory where the coverage files will be put
mkdir -p cov/fastest/
# Generate as many files than tests, since {n} is an unique number for each test
find tests/ -name "*Test.php" | vendor/liuggio/fastest/fastest "vendor/phpunit/phpunit/phpunit -c app {} --coverage-php cov/fastest/{n}.cov;"
# Merge the code coverage files
phpcov merge cov/fastest/ --html cov/merge/fastest/

代码覆盖率将在 cov/merge/fastest/ 目录中可用。

存储适配器

如果您想并行进行功能测试,并且您有一台4核CPU的机器,最好的做法是创建一个针对每个数据库的并行进程,fastest 让您能够轻松地与 Symfony 一起工作。

在 Symfony 中修改 config_test.yml 配置文件,每个功能测试将自动查找名为 <database_name>_test_x 的数据库(x 从 1 到 CPU 数量)。

Doctrine DBAL

config_test.yml

parameters:
    # Stubs
    doctrine.dbal.connection_factory.class: Liuggio\Fastest\Doctrine\DBAL\ConnectionFactory

Doctrine MongoDB 连接

config_test.yml

parameters:
    # Stubs
    doctrine_mongodb.odm.connection.class: Liuggio\Fastest\Doctrine\MongoDB\Connection

SQLite 数据库

SQLite 数据库没有名称。每个文件总是包含一个数据库。如果检测到 SQLite 驱动程序,则不会更改数据库名称,而是更改数据库路径。要使其正常工作,只需在数据库路径中添加 __DBNAME__ 占位符。

config_test.yml

doctrine:
    dbal:
        driver:   pdo_sqlite
        path:     "%kernel.cache_dir%/__DBNAME__.db"
        
parameters:
    doctrine.dbal.connection_factory.class: Liuggio\Fastest\Doctrine\DBAL\ConnectionFactory

__DBNAME__ 将被替换为 ENV_TEST_CHANNEL_READABLE 的值。

Behat.* 扩展

包含了一个 Behat 扩展,该扩展为 Behat 提供了输出将执行而无需实际执行的特征文件或单个场景列表的能力。此列表可以管道到 fastest 以并行运行场景。

要安装扩展,只需将其添加到您的 behat.yml 文件中

extensions:
    Liuggio\Fastest\Behat\ListFeaturesExtension\Extension: ~

for Behat2

extensions:
    Liuggio\Fastest\Behat2\ListFeaturesExtension\Extension: ~

之后,您将有两个额外的命令行选项:--list-features--list-scenarios。前者将输出 *.feature 文件列表,而后者将输出每个特征文件的每个场景,包括其行号(例如,/full/path/Features/myfeature.feature:lineNumber)

这可以让您直接将输出管道到 fastest 以并行化其执行

/my/path/behat --list-scenarios | ./vendor/liuggio/fastest/fastest "/my/path/behat {}"

使用 --list-scenarios 比使用 --list-features 更好,因为它将给出更详细的场景输出,允许 fastest 以更好的方式混合和平衡单个测试。

关于基于浏览器的测试(Selenium、Mink 等)

当浏览器通过 PHPUnit、Behat 或 Fastest 使用的其他测试套件远程控制时,浏览器会向服务器发送请求。问题是当服务器处理请求时,它不知道哪个 fastest 通道调用了它,因此必须在连接到数据库之前设置此信息(以便选择与通道对应的正确数据库)。

一种可能的方法是执行以下步骤

1. 设置一个 cookie、GET 查询参数或 HTTP 头部,包含适当的通道值

当您的测试场景开始时,可能在身份验证阶段,将以下之一设置为环境变量 ENV_TEST_CHANNEL_READABLE 的值

  • 如果它是一个 cookie 或 GET 查询参数,将其命名为 ENV_TEST_CHANNEL_READABLE
    • 请注意,如果您使用 GET 查询参数选项,并通过自动化点击浏览器中没有该查询参数的链接,则请求将不会包含查询参数,服务器将不知道通道以初始化。
  • 如果它是一个 HTTP 头部,将其命名为 X-FASTEST-ENV-TEST-CHANNEL-READABLE 并在每次请求服务器时发送。

2. 配置应用程序的入口点以设置请求的环境变量

为此,只需在启动应用程序之前添加以下代码即可

\Liuggio\Fastest\Environment\FastestEnvironment::setFromRequest();

这将检测 #1 中提到的任何上下文中 ENV_TEST_CHANNEL_READABLE 值的存在,并设置相应的环境变量。

例如,在 Symfony 框架的情况下,您只需将其添加到 web/app_dev.php 中,就在 require_once __DIR__.'/../app/AppKernel.php' 之前

// ... code
$loader = require_once __DIR__.'/../app/bootstrap.php.cache';
Debug::enable();

\Liuggio\Fastest\Environment\FastestEnvironment::setFromRequest();

require_once __DIR__.'/../app/AppKernel.php';
$kernel = new AppKernel('dev', true);
// ... code

安装

如果您使用 Composer,只需运行 composer require --dev 'liuggio/fastest:^1.6'

或者简单地将 liuggio/fastest 添加到您的项目 composer.json 文件中的依赖项

{
    "require-dev": {
	    "liuggio/fastest": "^1.6"
    }
}

对于通过 Composer 的系统级安装,您可以运行

使用 composer 全局安装 "liuggio/fastest=^1.6"

请确保您的路径中包含 ~/.composer/vendor/bin/,更多详情请参阅 getcomposer.org

如果您想与 phpunit 一起使用,可能需要安装 phpunit/phpunit 作为依赖项。

使用 fastest 运行此测试

Usage:
 fastest [-p|--process="..."] [-b|--before="..."] [-x|--xml="..."] [-o|--preserve-order] [--no-errors-summary] [execute]

Arguments:
 execute               Optional command to execute.

Options:
 --process (-p)        Number of parallel processes, default: available CPUs.
 --before (-b)         Execute a process before consuming the queue, it executes this command once per process, useful for init schema and load fixtures.
 --xml (-x)            Read input from a phpunit xml file from the '<testsuites>' collection. Note: it is not used for consuming.
 --preserve-order (-o) Queue is randomized by default, with this option the queue is read preserving the order.
 --rerun-failed (-r)   Re-run failed test with before command if exists.
 --no-errors-summary   Do not display all errors after the test run. Useful with --vv because it already displays errors immediately after they happen.
 --help (-h)           Display this help message.
 --quiet (-q)          Do not output any message.
 --verbose (-v|vv|vvv) Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug
 --version (-V)        Display this application version.
 --ansi                Force ANSI output.
 --no-ansi             Disable ANSI output.
 --no-interaction (-n) Do not ask any interactive question.

例如: ./fastest -x phpunit.xml.dist -v "bin/phpunit {}"

已知问题

如果您遇到未知命令错误,请确保您的 变量顺序 php.ini 设置包含 E。如果不包含,则环境变量未设置,且在您的 PATH 中的命令将无法工作。

贡献

请帮助我们通过代码、爱、反馈和错误报告。

感谢

  • @giorrrgio 为 mongoDB 适配器做出贡献
  • @diegosainz 为 Behat2 适配器做出贡献
  • 你呢?

许可证 License

阅读 LICENSE 了解更多信息。