在 PHPUnit 中重新运行上次失败的测试

发布于 2024-11-30 12:55:09 字数 120 浏览 1 评论 0原文

当其中一个测试失败时,您可以使用 --stop-on-failure 标志来中断单元测试。

有没有什么方法可以快速告诉 PHPUnit 重新运行这个失败的测试,而不是手动提供完整路径?

You may use --stop-on-failure flag to break the unit testing when one of the tests fails.

Is there any way quick way to tell PHPUnit to re-run this failed test, instead providing the full path manually?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

羞稚 2024-12-07 12:55:09

自 PHPUnit 7.3 起,您可以缓存测试结果,然后按缺陷对测试进行排序。

在 phpunit.xml 中,启用 cacheResults

<?xml version="1.0" encoding="UTF-8"?>
<phpunit cacheResult="true"
         ...>

如果您不想编辑 phpunit.xml,您还可以使用 --cache-result 标志运行测试。

缓存结果时,PHPUnit 将在运行测试后创建一个 .phpunit.result.cache 文件。确保将此文件添加到您的全局 gitignore 文件中。

您可以像这样运行测试以首先运行以前失败的测试:

phpunit --order-by=defects --stop-on-failure

Since PHPUnit 7.3, you can cache the results of your tests, then order your tests by defects.

In phpunit.xml, enable cacheResults:

<?xml version="1.0" encoding="UTF-8"?>
<phpunit cacheResult="true"
         ...>

If you don't want to edit your phpunit.xml, you could also run your tests with the --cache-result flag.

When caching results, PHPUnit will create a .phpunit.result.cache file after running tests. Make sure to add this file to your global gitignore file.

You can run your tests like this to run previously failed tests first:

phpunit --order-by=defects --stop-on-failure
烟雨凡馨 2024-12-07 12:55:09

查看 --filter cli 选项。您可以在组织文档命令行界面文档

--过滤器

仅运行名称与给定模式匹配的测试。该模式可以是单个测试的名称,也可以是匹配多个测试名称的正则表达式。

假设您的运行 phpunit Tests/Tests/Stuff/ThatOneTestClassAgain::testThisWorks 失败:

您的选项是:

phpunit --filter ThatOneTestClassAgain

phpunit --filter testThisWorks

或大多数其他有意义的字符串

Take a look at the --filter cli option. You can find an example in the organisation docs and in the CLI Docs.

--filter

Only runs tests whose name matches the given pattern. The pattern can be either the name of a single test or a regular expression that matches multiple test names.

Assume your run phpunit Tests/ and Tests/Stuff/ThatOneTestClassAgain::testThisWorks fails:

your options are:

phpunit --filter ThatOneTestClassAgain

and

phpunit --filter testThisWorks

or most other strings that somehow make sense

风和你 2024-12-07 12:55:09

我发现实现它的方法相当简单,但需要实现日志记录。您设置 phpunit 来记录到 json 文件。然后将 phpunit 命令更改为类似以下内容:

cd /home/vagrant/tests && php -d auto_prepend_file=./tests-prepend.php /usr/local/bin/phpunit

其作用是在执行 phpunit 之前 auto_prepend 一个 php 文件。这样我们就可以捕获 $argsv 并自动向 phpunit 提供所需的过滤命令。

tests-prepend.php
(请务必修改json日志的文件路径)

<?php

global $argv, $argc;
if(empty($argv) === false) {
    // are we re-running?
    $has_rerun = false;
    foreach ($argv as $key => $value) {
        if($value === '--rerun-failures') {
            $has_rerun = true;
            unset($argv[$key]);
            break;
        }
    }
    if($has_rerun === true) {
        // validate the path exists and if so then capture the json data.
        $path = realpath(dirname(__FILE__).'/../logs/report.json');
        if(is_file($path) === true) {
            // special consideration taken here as phpunit does not store the report as a json array.
            $data = json_decode('['.str_replace('}{'.PHP_EOL, '},{'.PHP_EOL, file_get_contents($path).']'), true);
            $failed = array();
            // capture the failures as well as errors but taking care not to capture skipped tests.
            foreach ($data as $event) {
                if($event['event'] === 'test') {
                    if($event['status'] === 'fail') {
                        $failed[] = array($event['test'], 'failed');
                    }
                    elseif($event['status'] === 'error' && $event['trace'][0]['function'] !== 'markTestIncomplete') {
                        $failed[] = array($event['test'], 'error\'d');
                    }
                }
            }
            if(empty($failed) === true) {
                echo 'There are no failed tests to re-run.'.PHP_EOL.PHP_EOL;
                exit;
            }
            else{
                echo '--------------------------------------------------------------------'.PHP_EOL;
                echo 'Re-running the following tests: '.PHP_EOL;
                foreach ($failed as $key => $test_data) {
                    echo ' - '.$test_data[0].' ('.$test_data[1].')'.PHP_EOL;
                    // important to escapre the namespace backslashes.
                    $failed[$key] = addslashes($test_data[0]);
                }
                echo '--------------------------------------------------------------------'.PHP_EOL.PHP_EOL;
            }
            $argv[] = '--filter';
            $argv[] = '/('.implode('|', $failed).')/';
            // important to update the globals in every location.
            $_SERVER['argv'] = $GLOBALS['_SERVER']['argv'] = $GLOBALS['argv'] = $argv = array_values($argv);
            $_SERVER['argc'] = $GLOBALS['_SERVER']['argc'] = $GLOBALS['argc'] = $argc = count($argv);
        }
        else{
            echo 'The last run report log at '.$path.' does not exist so it is not possible to re-run the failed tests. Please re-run the test suite without the --rerun-failures command.'.PHP_EOL.PHP_EOL;
            exit;
        }
    }
}

The way I've found to implement it is fairly easy, but requires logging to be implemented. You setup phpunit to log to a json file. Then you alter the phpunit command to something similar to:

cd /home/vagrant/tests && php -d auto_prepend_file=./tests-prepend.php /usr/local/bin/phpunit

What this does is auto_prepend a php file before the execution of phpunit. This way we can capture $argsv and supply the required filter command automatically to phpunit.

tests-prepend.php
(make sure to amend the file pathway of the json log)

<?php

global $argv, $argc;
if(empty($argv) === false) {
    // are we re-running?
    $has_rerun = false;
    foreach ($argv as $key => $value) {
        if($value === '--rerun-failures') {
            $has_rerun = true;
            unset($argv[$key]);
            break;
        }
    }
    if($has_rerun === true) {
        // validate the path exists and if so then capture the json data.
        $path = realpath(dirname(__FILE__).'/../logs/report.json');
        if(is_file($path) === true) {
            // special consideration taken here as phpunit does not store the report as a json array.
            $data = json_decode('['.str_replace('}{'.PHP_EOL, '},{'.PHP_EOL, file_get_contents($path).']'), true);
            $failed = array();
            // capture the failures as well as errors but taking care not to capture skipped tests.
            foreach ($data as $event) {
                if($event['event'] === 'test') {
                    if($event['status'] === 'fail') {
                        $failed[] = array($event['test'], 'failed');
                    }
                    elseif($event['status'] === 'error' && $event['trace'][0]['function'] !== 'markTestIncomplete') {
                        $failed[] = array($event['test'], 'error\'d');
                    }
                }
            }
            if(empty($failed) === true) {
                echo 'There are no failed tests to re-run.'.PHP_EOL.PHP_EOL;
                exit;
            }
            else{
                echo '--------------------------------------------------------------------'.PHP_EOL;
                echo 'Re-running the following tests: '.PHP_EOL;
                foreach ($failed as $key => $test_data) {
                    echo ' - '.$test_data[0].' ('.$test_data[1].')'.PHP_EOL;
                    // important to escapre the namespace backslashes.
                    $failed[$key] = addslashes($test_data[0]);
                }
                echo '--------------------------------------------------------------------'.PHP_EOL.PHP_EOL;
            }
            $argv[] = '--filter';
            $argv[] = '/('.implode('|', $failed).')/';
            // important to update the globals in every location.
            $_SERVER['argv'] = $GLOBALS['_SERVER']['argv'] = $GLOBALS['argv'] = $argv = array_values($argv);
            $_SERVER['argc'] = $GLOBALS['_SERVER']['argc'] = $GLOBALS['argc'] = $argc = count($argv);
        }
        else{
            echo 'The last run report log at '.$path.' does not exist so it is not possible to re-run the failed tests. Please re-run the test suite without the --rerun-failures command.'.PHP_EOL.PHP_EOL;
            exit;
        }
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文