diff --git a/composer.json b/composer.json index 6860c336..779f213d 100644 --- a/composer.json +++ b/composer.json @@ -43,7 +43,7 @@ "phpunit/php-code-coverage": "^10.0", "phpunit/php-file-iterator": "^4.0", "phpunit/php-timer": "^6.0", - "phpunit/phpunit": "^10.0.1", + "phpunit/phpunit": "^10.0.3", "sebastian/environment": "^6.0", "symfony/console": "^6.2.5", "symfony/process": "^6.2.5" diff --git a/src/Options.php b/src/Options.php index 406bbc0c..27228e1f 100644 --- a/src/Options.php +++ b/src/Options.php @@ -417,6 +417,12 @@ public static function setInputDefinition(InputDefinition $inputDefinition): voi '@see PHPUnit guide, chapter: ' . $chapter = 'Reporting', Configuration::COLOR_DEFAULT, ), + new InputOption( + 'no-progress', + null, + InputOption::VALUE_NONE, + '@see PHPUnit guide, chapter: ' . $chapter, + ), new InputOption( 'display-incomplete', null, diff --git a/src/ParaTestCommand.php b/src/ParaTestCommand.php index a0307dca..843f7dec 100644 --- a/src/ParaTestCommand.php +++ b/src/ParaTestCommand.php @@ -94,9 +94,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int $runner = new $runnerClass($options, $output); assert($runner instanceof RunnerInterface); - $runner->run(); - - return $runner->getExitCode(); + return $runner->run(); } private function displayHelp(OutputInterface $output): int diff --git a/src/RunnerInterface.php b/src/RunnerInterface.php index 9eef1e1e..eb2da2f6 100644 --- a/src/RunnerInterface.php +++ b/src/RunnerInterface.php @@ -10,7 +10,5 @@ interface RunnerInterface public const FAILURE_EXIT = 1; public const EXCEPTION_EXIT = 2; - public function run(): void; - - public function getExitCode(): int; + public function run(): int; } diff --git a/src/WrapperRunner/ResultPrinter.php b/src/WrapperRunner/ResultPrinter.php index 08df1036..eb1f29fe 100644 --- a/src/WrapperRunner/ResultPrinter.php +++ b/src/WrapperRunner/ResultPrinter.php @@ -26,6 +26,7 @@ use function fread; use function fseek; use function ftell; +use function fwrite; use function preg_replace; use function sprintf; use function str_repeat; @@ -46,10 +47,6 @@ final class ResultPrinter private int $column = 0; private int $casesProcessed = 0; private int $numberOfColumns = 80; - /** @var bool */ - private $needsTeamcity; - /** @var bool */ - private $printsTeamcity; /** @var resource|null */ private $teamcityLogFileHandle; /** @var array */ @@ -74,16 +71,14 @@ public function flush(): void { } }; -// $this->printsTeamcity = $this->options->teamcity(); -// $this->needsTeamcity = $this->options->needsTeamcity(); -// -// if (($teamcityLogFile = $this->options->logTeamcity()) === null) { -// return; -// } -// -// $teamcityLogFileHandle = fopen($teamcityLogFile, 'ab+'); -// assert($teamcityLogFileHandle !== false); -// $this->teamcityLogFileHandle = $teamcityLogFileHandle; + + if (! $this->options->configuration->hasLogfileTeamcity()) { + return; + } + + $teamcityLogFileHandle = fopen($this->options->configuration->logfileTeamcity(), 'ab+'); + assert($teamcityLogFileHandle !== false); + $this->teamcityLogFileHandle = $teamcityLogFileHandle; } public function setTestCount(int $testCount): void @@ -135,14 +130,67 @@ public function start(): void $output->write("\n"); } - public function println(string $string = ''): void + /** @param list $teamcityFiles */ + public function printFeedback(SplFileInfo $progressFile, array $teamcityFiles): void { - $this->column = 0; - $this->output->write($string . "\n"); + if ($this->options->needsTeamcity) { + $teamcityProgress = $this->tailMultiple($teamcityFiles); + + if ($this->teamcityLogFileHandle !== null) { + fwrite($this->teamcityLogFileHandle, $teamcityProgress); + } + } + + if ($this->options->configuration->outputIsTeamCity()) { + assert(isset($teamcityProgress)); + $this->output->write($teamcityProgress); + + return; + } + + if ($this->options->configuration->noProgress()) { + return; + } + + $feedbackItems = $this->tail($progressFile); + $feedbackItems = preg_replace('/ +\\d+ \\/ \\d+ \\(\\d+%\\)\\s*/', '', $feedbackItems); + + $actualTestCount = strlen($feedbackItems); + for ($index = 0; $index < $actualTestCount; ++$index) { + $this->printFeedbackItem($feedbackItems[$index]); + } } - public function printResults(TestResult $testResult): void + /** + * @param list $teamcityFiles + * @param list $testdoxFiles + */ + public function printResults(TestResult $testResult, array $teamcityFiles, array $testdoxFiles): void { + if ($this->options->needsTeamcity) { + $teamcityProgress = $this->tailMultiple($teamcityFiles); + + if ($this->teamcityLogFileHandle !== null) { + fwrite($this->teamcityLogFileHandle, $teamcityProgress); + $resource = $this->teamcityLogFileHandle; + $this->teamcityLogFileHandle = null; + fclose($resource); + } + } + + if ($this->options->configuration->outputIsTeamCity()) { + assert(isset($teamcityProgress)); + $this->output->write($teamcityProgress); + + return; + } + + if ($this->options->configuration->outputIsTestDox()) { + $this->output->write($this->tailMultiple($testdoxFiles)); + + return; + } + $resultPrinter = new DefaultResultPrinter( $this->printer, $this->options->configuration->displayDetailsOnIncompleteTests(), @@ -164,17 +212,6 @@ public function printResults(TestResult $testResult): void $summaryPrinter->print($testResult); } - public function printFeedback(SplFileInfo $progressFile): void - { - $feedbackItems = $this->tail($progressFile); - $feedbackItems = preg_replace('/ +\\d+ \\/ \\d+ \\(\\d+%\\)\\s*/', '', $feedbackItems); - - $actualTestCount = strlen($feedbackItems); - for ($index = 0; $index < $actualTestCount; ++$index) { - $this->printFeedbackItem($feedbackItems[$index]); - } - } - private function printFeedbackItem(string $item): void { $this->printFeedbackItemColor($item); @@ -192,8 +229,7 @@ private function printFeedbackItem(string $item): void $this->output->write(str_repeat(' ', $pad)); } - $this->output->write($this->getProgress()); - $this->println(); + $this->output->write($this->getProgress() . "\n"); } private function printFeedbackItemColor(string $item): void @@ -227,9 +263,24 @@ private function colorizeTextBox(string $color, string $buffer): string return Color::colorizeTextBox($color, $buffer); } - private function tail(SplFileInfo $progressFile): string + /** @param list $files */ + private function tailMultiple(array $files): string + { + $content = ''; + foreach ($files as $file) { + if (! $file->isFile()) { + continue; + } + + $content .= $this->tail($file); + } + + return $content; + } + + private function tail(SplFileInfo $file): string { - $path = $progressFile->getPathname(); + $path = $file->getPathname(); $handle = fopen($path, 'r'); assert($handle !== false); $fseek = fseek($handle, $this->tailPositions[$path] ?? 0); diff --git a/src/WrapperRunner/WrapperRunner.php b/src/WrapperRunner/WrapperRunner.php index 565fa49a..e8303f03 100644 --- a/src/WrapperRunner/WrapperRunner.php +++ b/src/WrapperRunner/WrapperRunner.php @@ -28,6 +28,7 @@ use function file_get_contents; use function max; use function realpath; +use function unlink; use function unserialize; use function usleep; @@ -86,7 +87,7 @@ public function __construct( $this->parameters = $parameters; } - public function run(): void + public function run(): int { ExcludeList::addDirectory(dirname(__DIR__)); TestResultFacade::init(); @@ -100,7 +101,8 @@ public function run(): void $this->startWorkers(); $this->assignAllPendingTests(); $this->waitForAllToFinish(); - $this->complete($result); + + return $this->complete($result); } public function getExitCode(): int @@ -138,10 +140,7 @@ private function assignAllPendingTests(): void if ( $this->exitcode > 0 - && ( - $this->options->configuration->stopOnFailure() - || $this->options->configuration->stopOnError() - ) + && $this->options->configuration->stopOnFailure() ) { $this->pending = []; } elseif (($pending = array_shift($this->pending)) !== null) { @@ -157,7 +156,10 @@ private function assignAllPendingTests(): void private function flushWorker(WrapperWorker $worker): void { $this->exitcode = max($this->exitcode, $worker->getExitCode()); - $this->printer->printFeedback($worker->progressFile); + $this->printer->printFeedback( + $worker->progressFile, + $this->teamcityFiles, + ); $worker->reset(); } @@ -229,7 +231,7 @@ private function destroyWorker(int $token): void unset($this->workers[$token]); } - private function complete(TestResult $testResultSum): void + private function complete(TestResult $testResultSum): int { foreach ($this->testresultFiles as $testresultFile) { if (! $testresultFile->isFile()) { @@ -248,6 +250,7 @@ private function complete(TestResult $testResultSum): void array_merge_recursive($testResultSum->testErroredEvents(), $testResult->testErroredEvents()), array_merge_recursive($testResultSum->testFailedEvents(), $testResult->testFailedEvents()), array_merge_recursive($testResultSum->testConsideredRiskyEvents(), $testResult->testConsideredRiskyEvents()), + array_merge_recursive($testResultSum->testSuiteSkippedEvents(), $testResult->testSuiteSkippedEvents()), array_merge_recursive($testResultSum->testSkippedEvents(), $testResult->testSkippedEvents()), array_merge_recursive($testResultSum->testMarkedIncompleteEvents(), $testResult->testMarkedIncompleteEvents()), array_merge_recursive($testResultSum->testTriggeredDeprecationEvents(), $testResult->testTriggeredDeprecationEvents()), @@ -265,11 +268,15 @@ private function complete(TestResult $testResultSum): void ); } - $this->printer->printResults($testResultSum); + $this->printer->printResults( + $testResultSum, + $this->teamcityFiles, + $this->testdoxFiles, + ); $this->generateCodeCoverageReports(); $this->generateLogs(); - $this->exitcode = (new ShellExitCodeCalculator())->calculate( + $exitcode = (new ShellExitCodeCalculator())->calculate( $this->options->configuration->failOnEmptyTestSuite(), $this->options->configuration->failOnRisky(), $this->options->configuration->failOnWarning(), @@ -277,6 +284,14 @@ private function complete(TestResult $testResultSum): void $this->options->configuration->failOnSkipped(), $testResultSum, ); + + $this->clearFiles($this->testresultFiles); + $this->clearFiles($this->coverageFiles); + $this->clearFiles($this->junitFiles); + $this->clearFiles($this->teamcityFiles); + $this->clearFiles($this->testdoxFiles); + + return $exitcode; } protected function generateCodeCoverageReports(): void @@ -309,4 +324,16 @@ private function generateLogs(): void $this->options->configuration->logfileJunit(), ); } + + /** @param list $files */ + private function clearFiles(array $files): void + { + foreach ($files as $file) { + if (! $file->isFile()) { + continue; + } + + unlink($file->getPathname()); + } + } } diff --git a/test/RunnerResult.php b/test/RunnerResult.php index 71f446f1..34a958bc 100644 --- a/test/RunnerResult.php +++ b/test/RunnerResult.php @@ -4,24 +4,12 @@ namespace ParaTest\Tests; +/** @immutable */ final class RunnerResult { - private int $exitCode; - private string $output; - - public function __construct(int $exitCode, string $output) - { - $this->exitCode = $exitCode; - $this->output = $output; - } - - public function getOutput(): string - { - return $this->output; - } - - public function getExitCode(): int - { - return $this->exitCode; + public function __construct( + public readonly int $exitCode, + public readonly string $output + ) { } } diff --git a/test/TestBase.php b/test/TestBase.php index db2976f5..31a7aa3d 100644 --- a/test/TestBase.php +++ b/test/TestBase.php @@ -78,7 +78,7 @@ final protected function runRunner(?string $cwd = null): RunnerResult unset($_SERVER[Options::ENV_KEY_UNIQUE_TOKEN]); } - $runner->run(); + $exitCode = $runner->run(); if ($shouldPutEnvForParatestTestingItSelf) { putenv(Options::ENV_KEY_TOKEN . '=' . $prevToken); putenv(Options::ENV_KEY_UNIQUE_TOKEN . '=' . $prevUniqueToken); @@ -86,7 +86,7 @@ final protected function runRunner(?string $cwd = null): RunnerResult $_SERVER[Options::ENV_KEY_UNIQUE_TOKEN] = $prevUniqueToken; } - return new RunnerResult($runner->getExitCode(), $output->fetch()); + return new RunnerResult($exitCode, $output->fetch()); } final protected function fixture(string $fixture): string diff --git a/test/Unit/WrapperRunner/ResultPrinterTest.php b/test/Unit/WrapperRunner/ResultPrinterTest.php index cc7e5026..3d4b5e3b 100644 --- a/test/Unit/WrapperRunner/ResultPrinterTest.php +++ b/test/Unit/WrapperRunner/ResultPrinterTest.php @@ -9,7 +9,6 @@ use ParaTest\WrapperRunner\ResultPrinter; use PHPUnit\TestRunner\TestResult\TestResult; use PHPUnit\TextUI\Configuration\Configuration; -use RuntimeException; use SebastianBergmann\Environment\Runtime; use SplFileInfo; use Symfony\Component\Console\Output\BufferedOutput; @@ -17,8 +16,8 @@ use function file_get_contents; use function file_put_contents; use function phpversion; -use function preg_match_all; use function sprintf; +use function uniqid; use const PHP_VERSION; @@ -120,7 +119,7 @@ public function testStartPrintsOptionInfoWithSingularForOneProcess(): void public function testGetHeader(): void { - $this->printer->printResults(new TestResult(0, 0, 0, [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [])); + $this->printer->printResults($this->getEmptyTestResult(), [], []); static::assertMatchesRegularExpression( "/\nTime: ([.:]?[0-9]{1,3})+ ?" . @@ -135,13 +134,13 @@ public function testPrintFeedbackForMixed(): void $this->printer->setTestCount(20); $feedbackFile = $this->tmpDir . DS . 'feedback1'; file_put_contents($feedbackFile, 'EWWFFFRRSSSS....... 19 / 19 (100%)'); - $this->printer->printFeedback(new SplFileInfo($feedbackFile)); + $this->printer->printFeedback(new SplFileInfo($feedbackFile), []); $contents = $this->output->fetch(); static::assertSame('EWWFFFRRSSSS.......', $contents); $feedbackFile = $this->tmpDir . DS . 'feedback2'; file_put_contents($feedbackFile, 'E 1 / 1 (100%)'); - $this->printer->printFeedback(new SplFileInfo($feedbackFile)); + $this->printer->printFeedback(new SplFileInfo($feedbackFile), []); $contents = $this->output->fetch(); static::assertSame("E 20 / 20 (100%)\n", $contents); } @@ -153,251 +152,92 @@ public function testColorsForFailing(): void $this->printer->setTestCount(20); $feedbackFile = $this->tmpDir . DS . 'feedback1'; file_put_contents($feedbackFile, 'E'); - $this->printer->printFeedback(new SplFileInfo($feedbackFile)); + $this->printer->printFeedback(new SplFileInfo($feedbackFile), []); $contents = $this->output->fetch(); static::assertStringContainsString('E', $contents); static::assertStringContainsString('31;1', $contents); } - public function testTeamcityEmptyLogFileRaiseException(): void - { - self::markTestIncomplete(); - $teamcityLog = $this->tmpDir . DS . 'teamcity.log'; - - $this->options = $this->createOptionsFromArgv(['--log-teamcity' => $teamcityLog]); - $this->printer = new ResultPrinter($this->interpreter, $this->output, $this->options); - - $test = $this->getSuiteWithResult('single-passing.xml', 1); - - file_put_contents($test->getTeamcityTempFile(), ''); - $this->expectException(RuntimeException::class); - $this->expectExceptionMessageMatches('/Teamcity/'); - - $this->printer->printFeedback($test); - } - public function testTeamcityFeedbackOnFile(): void { - self::markTestIncomplete(); + $teamcitySource = $this->tmpDir . DS . 'source'; + $teamcitySourceContent = uniqid('##teamcity_'); + file_put_contents($teamcitySource, $teamcitySourceContent); $teamcityLog = $this->tmpDir . DS . 'teamcity2.log'; $this->options = $this->createOptionsFromArgv(['--log-teamcity' => $teamcityLog]); - $this->printer = new ResultPrinter($this->interpreter, $this->output, $this->options); - $this->printer->addTest($this->passingSuite); + $this->printer = new ResultPrinter($this->output, $this->options); - $this->printer->start(); - $this->printer->printFeedback($this->passingSuite); - $this->printer->printResults(); + $this->printer->setTestCount(20); + $feedbackFile = $this->tmpDir . DS . 'feedback1'; + file_put_contents($feedbackFile, 'E'); - static::assertStringContainsString('OK', $this->output->fetch()); + $this->printer->printFeedback(new SplFileInfo($feedbackFile), [new SplFileInfo($teamcitySource)]); + + static::assertSame('E', $this->output->fetch()); static::assertFileExists($teamcityLog); $logContent = file_get_contents($teamcityLog); self::assertNotFalse($logContent); - self::assertSame(9, preg_match_all('/^##teamcity/m', $logContent)); + self::assertSame($teamcitySourceContent, $logContent); } public function testTeamcityFeedbackOnStdout(): void { - self::markTestIncomplete(); + $teamcitySource = $this->tmpDir . DS . 'source'; + $teamcitySourceContent = uniqid('##teamcity_'); + file_put_contents($teamcitySource, $teamcitySourceContent); + $this->options = $this->createOptionsFromArgv(['--teamcity' => true]); - $this->printer = new ResultPrinter($this->interpreter, $this->output, $this->options); - $this->printer->addTest($this->passingSuite); + $this->printer = new ResultPrinter($this->output, $this->options); - $this->printer->start(); - $this->printer->printFeedback($this->passingSuite); - $this->printer->printResults(); + $this->printer->setTestCount(20); + $feedbackFile = $this->tmpDir . DS . 'feedback1'; + file_put_contents($feedbackFile, 'E'); - $output = $this->output->fetch(); - static::assertStringContainsString('OK', $output); - self::assertSame(9, preg_match_all('/^##teamcity/m', $output)); + $this->printer->printFeedback(new SplFileInfo($feedbackFile), [new SplFileInfo($teamcitySource)]); + $this->printer->printResults($this->getEmptyTestResult(), [new SplFileInfo($teamcitySource)], []); + + static::assertSame($teamcitySourceContent, $this->output->fetch()); } - public function testTestdoxOutputNonVerbose(): void + public function testTestdoxOutputWithProgress(): void { - self::markTestIncomplete(); - $options = $this->createOptionsFromArgv(['--testdox' => true, '--verbose' => false]); - $printer = new ResultPrinter($this->interpreter, $this->output, $options); - $printer->printFeedback($this->mixedSuite); - $contents = $this->output->fetch(); + $testdoxSource = $this->tmpDir . DS . 'source'; + $testdoxSourceContent = uniqid('Success!'); + file_put_contents($testdoxSource, $testdoxSourceContent); + + $this->options = $this->createOptionsFromArgv(['--testdox' => true]); + $this->printer = new ResultPrinter($this->output, $this->options); + + $this->printer->setTestCount(20); + $feedbackFile = $this->tmpDir . DS . 'feedback1'; + file_put_contents($feedbackFile, 'EEE'); + + $this->printer->printFeedback(new SplFileInfo($feedbackFile), []); + $this->printer->printResults($this->getEmptyTestResult(), [], [new SplFileInfo($testdoxSource)]); - $expected = <<<'EOF' -Unit Test With Class Annotation (ParaTest\Tests\fixtures\failing_tests\UnitTestWithClassAnnotation) - ✔ Truth - ✘ Falsehood - │ - │ Failed asserting that true is false. - │ - │ ./test/fixtures/failing_tests/UnitTestWithClassAnnotationTest.php:32 - │ - - ✔ Array length - ✔ Its a test - -Unit Test With Error (ParaTest\Tests\fixtures\failing_tests\UnitTestWithError) - ✘ Truth - │ - │ RuntimeException: Error!!! - │ - │ ./test/fixtures/failing_tests/UnitTestWithErrorTest.php:19 - │ - - ✔ Is it false - ✘ Falsehood - │ - │ Failed asserting that two strings are identical. - │ --- Expected - │ +++ Actual - │ @@ @@ - │ -'foo' - │ +'bar' - │ - │ ./test/fixtures/failing_tests/UnitTestWithMethodAnnotationsTest.php:21 - │ - - ✔ Array length - ⚠ Warning - │ - │ MyWarning - │ - - ↩ Skipped - ↩ Incomplete - ☢ Risky - -Unit Test With Method Annotations (ParaTest\Tests\fixtures\failing_tests\UnitTestWithMethodAnnotations) - ✔ Truth - ✘ Falsehood - │ - │ Failed asserting that two strings are identical. - │ --- Expected - │ +++ Actual - │ @@ @@ - │ -'foo' - │ +'bar' - │ - │ ./test/fixtures/failing_tests/UnitTestWithMethodAnnotationsTest.php:21 - │ - - ✔ Array length - ⚠ Warning - │ - │ MyWarning - │ - - ↩ Skipped - ↩ Incomplete - ☢ Risky - - -EOF; - - static::assertSame($expected, $contents); + static::assertSame('EEE' . $testdoxSourceContent, $this->output->fetch()); } - public function testTestdoxOutputVerbose(): void + public function testTestdoxOutputWithoutProgress(): void { - self::markTestIncomplete(); - $options = $this->createOptionsFromArgv(['--testdox' => true, '--verbose' => true]); - $printer = new ResultPrinter($this->interpreter, $this->output, $options); - $printer->printFeedback($this->mixedSuite); - $contents = $this->output->fetch(); + $testdoxSource = $this->tmpDir . DS . 'source'; + $testdoxSourceContent = uniqid('Success!'); + file_put_contents($testdoxSource, $testdoxSourceContent); - $expected = <<<'EOF' -Unit Test With Class Annotation (ParaTest\Tests\fixtures\failing_tests\UnitTestWithClassAnnotation) - ✔ Truth [1234.57 ms] - ✘ Falsehood [1234.57 ms] - │ - │ Failed asserting that true is false. - │ - │ ./test/fixtures/failing_tests/UnitTestWithClassAnnotationTest.php:32 - │ - - ✔ Array length [1234.57 ms] - ✔ Its a test [1234.57 ms] - -Unit Test With Error (ParaTest\Tests\fixtures\failing_tests\UnitTestWithError) - ✘ Truth [1234.57 ms] - │ - │ RuntimeException: Error!!! - │ - │ ./test/fixtures/failing_tests/UnitTestWithErrorTest.php:19 - │ - - ✔ Is it false [1234.57 ms] - ✘ Falsehood [1234.57 ms] - │ - │ Failed asserting that two strings are identical. - │ --- Expected - │ +++ Actual - │ @@ @@ - │ -'foo' - │ +'bar' - │ - │ ./test/fixtures/failing_tests/UnitTestWithMethodAnnotationsTest.php:21 - │ - - ✔ Array length [1234.57 ms] - ⚠ Warning [1234.57 ms] - │ - │ MyWarning - │ - - ↩ Skipped [1234.57 ms] - │ - │ ./test/fixtures/failing_tests/UnitTestWithMethodAnnotationsTest.php:39 - │ - - ↩ Incomplete [1234.57 ms] - │ - │ ./test/fixtures/failing_tests/UnitTestWithMethodAnnotationsTest.php:45 - │ - - ☢ Risky [1234.57 ms] - │ - │ This test did not perform any assertions - │ - -Unit Test With Method Annotations (ParaTest\Tests\fixtures\failing_tests\UnitTestWithMethodAnnotations) - ✔ Truth [1234.57 ms] - ✘ Falsehood [1234.57 ms] - │ - │ Failed asserting that two strings are identical. - │ --- Expected - │ +++ Actual - │ @@ @@ - │ -'foo' - │ +'bar' - │ - │ ./test/fixtures/failing_tests/UnitTestWithMethodAnnotationsTest.php:21 - │ - - ✔ Array length [1234.57 ms] - ⚠ Warning [1234.57 ms] - │ - │ MyWarning - │ - - ↩ Skipped [1234.57 ms] - │ - │ ./test/fixtures/failing_tests/UnitTestWithMethodAnnotationsTest.php:39 - │ - - ↩ Incomplete [1234.57 ms] - │ - │ ./test/fixtures/failing_tests/UnitTestWithMethodAnnotationsTest.php:45 - │ - - ☢ Risky [1234.57 ms] - │ - │ This test did not perform any assertions - │ - - -EOF; - - static::assertSame($expected, $contents); + $this->options = $this->createOptionsFromArgv(['--testdox' => true, '--no-progress' => true]); + $this->printer = new ResultPrinter($this->output, $this->options); + + $this->printer->setTestCount(20); + $feedbackFile = $this->tmpDir . DS . 'feedback1'; + file_put_contents($feedbackFile, 'EEE'); + + $this->printer->printFeedback(new SplFileInfo($feedbackFile), []); + $this->printer->printResults($this->getEmptyTestResult(), [], [new SplFileInfo($testdoxSource)]); + + static::assertSame($testdoxSourceContent, $this->output->fetch()); } private function getStartOutput(): string @@ -406,4 +246,31 @@ private function getStartOutput(): string return $this->output->fetch(); } + + private function getEmptyTestResult(): TestResult + { + return new TestResult( + 0, + 0, + 0, + [], + [], + [], + [], + [], + [], + [], + [], + [], + [], + [], + [], + [], + [], + [], + [], + [], + [], + ); + } } diff --git a/test/Unit/WrapperRunner/WrapperRunnerTest.php b/test/Unit/WrapperRunner/WrapperRunnerTest.php index 2bacc2ed..884d868b 100644 --- a/test/Unit/WrapperRunner/WrapperRunnerTest.php +++ b/test/Unit/WrapperRunner/WrapperRunnerTest.php @@ -18,7 +18,6 @@ use function file_get_contents; use function min; use function posix_mkfifo; -use function preg_match; use function preg_match_all; use function scandir; use function simplexml_load_file; @@ -107,7 +106,7 @@ public function testReadPhpunitConfigPhpSectionBeforeLoadingTheSuite(): void { $this->bareOptions['--configuration'] = $this->fixture('github' . DS . 'GH420' . DS . 'phpunit.xml'); $runnerResult = $this->runRunner(); - static::assertEquals(0, $runnerResult->getExitCode()); + static::assertEquals(0, $runnerResult->exitCode); } public function testRunnerSortTestEqualBySeed(): void @@ -123,15 +122,15 @@ public function testRunnerSortTestEqualBySeed(): void $runnerResultFirst = $this->runRunner(); $runnerResultSecond = $this->runRunner(); - $firstOutput = $this->prepareOutputForTestOrderCheck($runnerResultFirst->getOutput()); - $secondOutput = $this->prepareOutputForTestOrderCheck($runnerResultSecond->getOutput()); + $firstOutput = $this->prepareOutputForTestOrderCheck($runnerResultFirst->output); + $secondOutput = $this->prepareOutputForTestOrderCheck($runnerResultSecond->output); Assert::assertSame($firstOutput, $secondOutput); $this->bareOptions['--random-order-seed'] = '321'; $runnerResultThird = $this->runRunner(); - $thirdOutput = $this->prepareOutputForTestOrderCheck($runnerResultThird->getOutput()); + $thirdOutput = $this->prepareOutputForTestOrderCheck($runnerResultThird->output); Assert::assertNotSame($thirdOutput, $firstOutput); } @@ -157,7 +156,7 @@ public function testRunnerSortNoSeedProvided(): void $runnerResult = $this->runRunner(); - Assert::assertStringContainsString('Random Seed:', $runnerResult->getOutput()); + Assert::assertStringContainsString('Random Seed:', $runnerResult->output); } /** @@ -171,11 +170,11 @@ public function testErrorsInDataProviderAreHandled(): void $this->bareOptions['--configuration'] = $this->fixture('github' . DS . 'GH565' . DS . 'phpunit.xml'); $runnerResult = $this->runRunner(); - Assert::assertStringContainsString('The data provider specified for ParaTest\Tests\fixtures\github\GH565\IssueTest::testIncompleteByDataProvider is invalid', $runnerResult->getOutput()); - Assert::assertStringContainsString('The data provider specified for ParaTest\Tests\fixtures\github\GH565\IssueTest::testSkippedByDataProvider is invalid', $runnerResult->getOutput()); - Assert::assertStringContainsString('The data provider specified for ParaTest\Tests\fixtures\github\GH565\IssueTest::testErrorByDataProvider is invalid', $runnerResult->getOutput()); - Assert::assertStringContainsString('Warnings: 1', $runnerResult->getOutput()); - Assert::assertEquals(RunnerInterface::EXCEPTION_EXIT, $runnerResult->getExitCode()); + Assert::assertStringContainsString('The data provider specified for ParaTest\Tests\fixtures\github\GH565\IssueTest::testIncompleteByDataProvider is invalid', $runnerResult->output); + Assert::assertStringContainsString('The data provider specified for ParaTest\Tests\fixtures\github\GH565\IssueTest::testSkippedByDataProvider is invalid', $runnerResult->output); + Assert::assertStringContainsString('The data provider specified for ParaTest\Tests\fixtures\github\GH565\IssueTest::testErrorByDataProvider is invalid', $runnerResult->output); + Assert::assertStringContainsString('Warnings: 1', $runnerResult->output); + Assert::assertEquals(RunnerInterface::EXCEPTION_EXIT, $runnerResult->exitCode); } public function testParatestEnvironmentVariableWithWrapperRunnerWithoutTestTokens(): void @@ -185,15 +184,15 @@ public function testParatestEnvironmentVariableWithWrapperRunnerWithoutTestToken $runnerResult = $this->runRunner(); - Assert::assertStringContainsString('Failures: 1', $runnerResult->getOutput()); - Assert::assertEquals(RunnerInterface::FAILURE_EXIT, $runnerResult->getExitCode()); + Assert::assertStringContainsString('Failures: 1', $runnerResult->output); + Assert::assertEquals(RunnerInterface::FAILURE_EXIT, $runnerResult->exitCode); } public function testParatestEnvironmentVariable(): void { $this->bareOptions['path'] = $this->fixture('paratest_only_tests' . DS . 'EnvironmentTest.php'); - static::assertEquals(0, $this->runRunner()->getExitCode()); + static::assertEquals(0, $this->runRunner()->exitCode); } public function testPassthrus(): void @@ -201,7 +200,7 @@ public function testPassthrus(): void $this->bareOptions['path'] = $this->fixture('passthru_tests' . DS . 'PassthruTest.php'); $runnerResult = $this->runRunner(); - Assert::assertSame(RunnerInterface::FAILURE_EXIT, $runnerResult->getExitCode()); + Assert::assertSame(RunnerInterface::FAILURE_EXIT, $runnerResult->exitCode); $this->bareOptions['--passthru-php'] = sprintf("'-d' 'highlight.comment=%s'", self::PASSTHRU_PHP_CUSTOM); if (defined('PHP_WINDOWS_VERSION_BUILD')) { @@ -209,7 +208,7 @@ public function testPassthrus(): void } $runnerResult = $this->runRunner(); - static::assertEquals(0, $runnerResult->getExitCode()); + static::assertEquals(0, $runnerResult->exitCode); } /** @@ -222,20 +221,17 @@ public function testReadPhpunitConfigPhpSectionBeforeLoadingTheSuiteManualBootst $this->bareOptions['--bootstrap'] = $this->fixture('github' . DS . 'GH420bis' . DS . 'bootstrap.php'); $runnerResult = $this->runRunner(); - static::assertEquals(0, $runnerResult->getExitCode()); + static::assertEquals(0, $runnerResult->exitCode); } public function testTeamcityOutput(): void { - self::markTestIncomplete(); - $this->bareOptions = [ - '--configuration' => $this->fixture('phpunit-passing.xml'), - '--teamcity' => true, - ]; + $this->bareOptions['path'] = $this->fixture('common_results'); + $this->bareOptions['--teamcity'] = true; $result = $this->runRunner(); - Assert::assertSame(66, preg_match_all('/^##teamcity/m', $result->getOutput())); + Assert::assertSame(35, preg_match_all('/^##teamcity/m', $result->output)); } public function testExitCodesPathWithoutTests(): void @@ -243,20 +239,17 @@ public function testExitCodesPathWithoutTests(): void $this->bareOptions['path'] = $this->fixture('no_tests'); $runnerResult = $this->runRunner(); - Assert::assertEquals(RunnerInterface::SUCCESS_EXIT, $runnerResult->getExitCode()); + Assert::assertEquals(RunnerInterface::SUCCESS_EXIT, $runnerResult->exitCode); } /** @requires OSFAMILY Linux */ public function testTeamcityLogHandlesFifoFiles(): void { - self::markTestIncomplete(); $outputPath = $this->tmpDir . DS . 'test-output.teamcity'; posix_mkfifo($outputPath, 0600); - $this->bareOptions = [ - '--configuration' => $this->fixture('phpunit-passing.xml'), - '--log-teamcity' => $outputPath, - ]; + $this->bareOptions['path'] = $this->fixture('common_results' . DS . 'SuccessTest.php'); + $this->bareOptions['--log-teamcity'] = $outputPath; $fifoReader = new Process(['cat', $outputPath]); $fifoReader->start(); @@ -264,29 +257,19 @@ public function testTeamcityLogHandlesFifoFiles(): void $this->runRunner(); Assert::assertSame(0, $fifoReader->wait()); - Assert::assertSame(66, preg_match_all('/^##teamcity/m', $fifoReader->getOutput())); + Assert::assertSame(5, preg_match_all('/^##teamcity/m', $fifoReader->getOutput())); } public function testStopOnFailureEndsRunBeforeWholeTestSuite(): void { $this->bareOptions['--processes'] = '1'; $this->bareOptions['path'] = $this->fixture('common_results'); - $runnerResult = $this->runRunner(); - - $regexp = '/Tests: \d+, Assertions: \d+, Errors: \d+, Failures: \d+, Warnings: \d+, Skipped: \d+, Incomplete: \d+, Risky: \d+\./'; - $output = $runnerResult->getOutput(); - Assert::assertMatchesRegularExpression($regexp, $output); - Assert::assertSame(1, preg_match($regexp, $output, $matchesOnFullRun)); + $output = $this->runRunner()->output; + self::assertStringContainsString('Tests: 59, Assertions: 185,', $output); $this->bareOptions['--stop-on-failure'] = true; - $runnerResult = $this->runRunner(); - - $regexp = '/Tests: \d+, Assertions: \d+, Errors: \d+, Skipped: \d+, Incomplete: \d+\./'; - $output = $runnerResult->getOutput(); - Assert::assertMatchesRegularExpression($regexp, $output); - Assert::assertSame(1, preg_match($regexp, $output, $matchesOnPartialRun)); - - Assert::assertNotEquals($matchesOnFullRun[0], $matchesOnPartialRun[0]); + $output = $this->runRunner()->output; + self::assertStringContainsString('Tests: 53, Assertions: 182,', $output); } public function testRaiseExceptionWhenATestCallsExitWithoutCoverageSingleProcess(): void @@ -351,27 +334,27 @@ public function testExitCodes(): void $this->bareOptions['path'] = $this->fixture('common_results' . DS . 'ErrorTest.php'); $runnerResult = $this->runRunner(); - Assert::assertStringContainsString('Errors: 1', $runnerResult->getOutput()); - Assert::assertEquals(RunnerInterface::EXCEPTION_EXIT, $runnerResult->getExitCode()); + Assert::assertStringContainsString('Errors: 1', $runnerResult->output); + Assert::assertEquals(RunnerInterface::EXCEPTION_EXIT, $runnerResult->exitCode); $this->bareOptions['path'] = $this->fixture('common_results' . DS . 'FailureTest.php'); $runnerResult = $this->runRunner(); - Assert::assertStringContainsString('Failures: 1', $runnerResult->getOutput()); - Assert::assertEquals(RunnerInterface::FAILURE_EXIT, $runnerResult->getExitCode()); + Assert::assertStringContainsString('Failures: 1', $runnerResult->output); + Assert::assertEquals(RunnerInterface::FAILURE_EXIT, $runnerResult->exitCode); $this->bareOptions['path'] = $this->fixture('common_results' . DS . 'SuccessTest.php'); $runnerResult = $this->runRunner(); - Assert::assertStringContainsString('OK', $runnerResult->getOutput()); - Assert::assertEquals(RunnerInterface::SUCCESS_EXIT, $runnerResult->getExitCode()); + Assert::assertStringContainsString('OK', $runnerResult->output); + Assert::assertEquals(RunnerInterface::SUCCESS_EXIT, $runnerResult->exitCode); $this->bareOptions['path'] = $this->fixture('common_results'); $runnerResult = $this->runRunner(); - Assert::assertStringContainsString('Failures: 1', $runnerResult->getOutput()); - Assert::assertStringContainsString('Errors: 1', $runnerResult->getOutput()); - Assert::assertEquals(RunnerInterface::EXCEPTION_EXIT, $runnerResult->getExitCode()); + Assert::assertStringContainsString('Failures: 1', $runnerResult->output); + Assert::assertStringContainsString('Errors: 1', $runnerResult->output); + Assert::assertEquals(RunnerInterface::EXCEPTION_EXIT, $runnerResult->exitCode); } public function testWritesLogWithEmptyNameWhenPathIsNotProvided(): void @@ -405,12 +388,12 @@ public function testRunnerReversed(): void ]; $runnerResult = $this->runRunner(); - $defaultOrder = $this->prepareOutputForTestOrderCheck($runnerResult->getOutput()); + $defaultOrder = $this->prepareOutputForTestOrderCheck($runnerResult->output); $this->bareOptions['--order-by'] = 'reverse'; $runnerResult = $this->runRunner(); - $reverseOrder = $this->prepareOutputForTestOrderCheck($runnerResult->getOutput()); + $reverseOrder = $this->prepareOutputForTestOrderCheck($runnerResult->output); $reverseOrderReversed = array_reverse($reverseOrder); @@ -428,7 +411,7 @@ public function testTokensAreAbsentWhenNoTestTokensIsSpecified(): void $this->bareOptions['path'] = $this->fixture('github' . DS . 'GH505'); $runnerResult = $this->runRunner(); - static::assertEquals(0, $runnerResult->getExitCode()); + static::assertEquals(0, $runnerResult->exitCode); } /** @@ -445,18 +428,15 @@ public function testRandomnessIsDeterministic(): void ]; $runnerResult = $this->runRunner(); - static::assertEquals(0, $runnerResult->getExitCode()); + static::assertEquals(0, $runnerResult->exitCode); } public function testTeamcityLog(): void { - self::markTestIncomplete(); $outputPath = $this->tmpDir . DS . 'test-output.teamcity'; - $this->bareOptions = [ - '--configuration' => $this->fixture('phpunit-passing.xml'), - '--log-teamcity' => $outputPath, - ]; + $this->bareOptions['path'] = $this->fixture('common_results'); + $this->bareOptions['--log-teamcity'] = $outputPath; $this->runRunner(); @@ -464,7 +444,7 @@ public function testTeamcityLog(): void $content = file_get_contents($outputPath); Assert::assertNotFalse($content); - Assert::assertSame(66, preg_match_all('/^##teamcity/m', $content)); + Assert::assertSame(35, preg_match_all('/^##teamcity/m', $content)); } public function testRunningFewerTestsThanTheWorkersIsPossible(): void @@ -473,7 +453,7 @@ public function testRunningFewerTestsThanTheWorkersIsPossible(): void $this->bareOptions['--processes'] = '10'; $runnerResult = $this->runRunner(); - static::assertEquals(0, $runnerResult->getExitCode()); + static::assertEquals(0, $runnerResult->exitCode); } public function testResultsAreCorrect(): void @@ -484,7 +464,7 @@ public function testResultsAreCorrect(): void $this->bareOptions['--cache-directory'] = $this->tmpDir; $runnerResult = $this->runRunner(); - static::assertEquals(0, $runnerResult->getExitCode()); + static::assertEquals(0, $runnerResult->exitCode); $coveragePhp = include $this->bareOptions['--coverage-php']; Assert::assertInstanceOf(CodeCoverage::class, $coveragePhp); @@ -495,6 +475,6 @@ public function testHandleCollisionWithSymfonyOutput(): void $this->bareOptions['path'] = $this->fixture('symfony_output_collision' . DS . 'FailingSymfonyOutputCollisionTest.php'); $runnerResult = $this->runRunner(); - static::assertStringContainsString('', $runnerResult->getOutput()); + static::assertStringContainsString('', $runnerResult->output); } }