Повторный запуск последнего неудачного теста в PHPUnit

Вы можете использовать флаг --stop-on-failure, чтобы сломать модульное тестирование, когда один из тестов завершился с ошибкой.

Есть ли какой-нибудь быстрый способ сказать PHPUnit повторно запустить этот неудачный тест, вместо этого предоставив полный путь вручную?

Ответ 1

Взгляните на параметр --filter cli. Вы можете найти пример в organisation docs и в CLI Docs.

- фильтр

Выполняет только те тесты, чье имя соответствует заданному шаблону. Шаблон может быть либо именем одного теста, либо регулярным выражением, которое соответствует нескольким именам тестов.

Предположим, что ваш запуск phpunit Tests/ и Tests/Stuff/ThatOneTestClassAgain::testThisWorks завершается с ошибкой:

ваши варианты:

phpunit --filter ThatOneTestClassAgain

и

phpunit --filter testThisWorks

или большинство других строк, которые каким-то образом имеют смысл

Ответ 2

То, как я нашел его реализовать, довольно просто, но требует, чтобы протоколирование выполнялось. Вы устанавливаете phpunit для входа в json файл. Затем вы изменяете команду phpunit на что-то похожее:

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

То, что это делает, - auto_prepend php файл перед выполнением phpunit. Таким образом, мы можем захватить $argsv и автоматически предоставить необходимую команду фильтра phpunit.

Тесты-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;
        }
    }
}

Ответ 3

Начиная с PhpUnit 7.3, вы можете кэшировать результаты ваших тестов, а затем упорядочивать ваши тесты по дефектам.

В phpunit.xml включите cacheResults:

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

Если вы не хотите редактировать свой phpunit.xml, вы также можете запустить свои тесты с --cache-results.

При кэшировании результатов .phpunit.result.cache файл .phpunit.result.cache после выполнения тестов (обязательно добавьте этот файл в ваш (глобальный) файл gitignore).

Вы можете запустить свои тесты следующим образом, чтобы сначала запустить ранее провалившиеся тесты:

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