This commit is contained in:
Luke Downing
2023-02-06 16:58:34 +00:00
committed by Nuno Maduro
parent 48309931ef
commit 2929af4715
2 changed files with 154 additions and 17 deletions

View File

@ -0,0 +1,91 @@
<?php
declare(strict_types=1);
use ParaTest\WrapperRunner\ApplicationForWrapperWorker;
use ParaTest\WrapperRunner\WrapperWorker;
use Pest\ConfigLoader;
use Pest\TestSuite;
use Symfony\Component\Console\Input\ArgvInput;
(static function (): void {
$getopt = getopt('', [
'status-file:',
'progress-file:',
'testresult-file:',
'teamcity-file:',
'testdox-file:',
'testdox-color',
'phpunit-argv:',
]);
require_once __DIR__ . '/../overrides/Runner/TestSuiteLoader.php';
require_once __DIR__ . '/../overrides/Runner/Filter/NameFilterIterator.php';
$composerAutoloadFiles = [
dirname(__DIR__, 3) . DIRECTORY_SEPARATOR . 'autoload.php',
dirname(__DIR__, 2) . DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . 'autoload.php',
dirname(__DIR__) . DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . 'autoload.php',
];
foreach ($composerAutoloadFiles as $file) {
if (file_exists($file)) {
require_once $file;
define('PHPUNIT_COMPOSER_INSTALL', $file);
break;
}
}
assert(isset($getopt['status-file']) && is_string($getopt['status-file']));
$statusFile = fopen($getopt['status-file'], 'wb');
assert(is_resource($statusFile));
assert(isset($getopt['progress-file']) && is_string($getopt['progress-file']));
assert(isset($getopt['testresult-file']) && is_string($getopt['testresult-file']));
assert(!isset($getopt['teamcity-file']) || is_string($getopt['teamcity-file']));
assert(!isset($getopt['testdox-file']) || is_string($getopt['testdox-file']));
assert(isset($getopt['phpunit-argv']) && is_string($getopt['phpunit-argv']));
$phpunitArgv = unserialize($getopt['phpunit-argv'], ['allowed_classes' => false]);
assert(is_array($phpunitArgv));
/**
* We need to instantiate the Pest Test suite instance
* so that Pest is able to execute correctly.
*/
$argv = new ArgvInput();
$rootPath = dirname(PHPUNIT_COMPOSER_INSTALL, 2);
TestSuite::getInstance(
$rootPath,
$argv->getParameterOption('--test-directory', (new ConfigLoader($rootPath))->getTestsDirectory()),
);
$application = new ApplicationForWrapperWorker(
$phpunitArgv,
$getopt['progress-file'],
$getopt['testresult-file'],
$getopt['teamcity-file'] ?? null,
$getopt['testdox-file'] ?? null,
isset($getopt['testdox-color']),
);
while (true) {
if (feof(STDIN)) {
$application->end();
exit;
}
$testPath = fgets(STDIN);
if ($testPath === false || $testPath === WrapperWorker::COMMAND_EXIT) {
$application->end();
exit;
}
// It must be a 1 byte string to ensure filesize() is equal to the number of tests executed
$exitCode = $application->runTest(trim($testPath));
fwrite($statusFile, (string) $exitCode);
fflush($statusFile);
}
})();

View File

@ -12,6 +12,7 @@ use ParaTest\RunnerInterface;
use ParaTest\WrapperRunner\ResultPrinter; use ParaTest\WrapperRunner\ResultPrinter;
use ParaTest\WrapperRunner\SuiteLoader; use ParaTest\WrapperRunner\SuiteLoader;
use ParaTest\WrapperRunner\WrapperWorker; use ParaTest\WrapperRunner\WrapperWorker;
use Pest\TestSuite;
use PHPUnit\Event\Facade as EventFacade; use PHPUnit\Event\Facade as EventFacade;
use PHPUnit\Runner\CodeCoverage; use PHPUnit\Runner\CodeCoverage;
use PHPUnit\TestRunner\TestResult\Facade as TestResultFacade; use PHPUnit\TestRunner\TestResult\Facade as TestResultFacade;
@ -31,6 +32,7 @@ use function dirname;
use function file_get_contents; use function file_get_contents;
use function max; use function max;
use function realpath; use function realpath;
use function unlink;
use function unserialize; use function unserialize;
use function usleep; use function usleep;
@ -50,15 +52,15 @@ final class WrapperRunner implements RunnerInterface
/** @var array<int,int> */ /** @var array<int,int> */
private array $batches = []; private array $batches = [];
/** @var SplFileInfo */ /** @var list<SplFileInfo> */
private array $testresultFiles = []; private array $testresultFiles = [];
/** @var SplFileInfo */ /** @var list<SplFileInfo> */
private array $coverageFiles = []; private array $coverageFiles = [];
/** @var SplFileInfo */ /** @var list<SplFileInfo> */
private array $junitFiles = []; private array $junitFiles = [];
/** @var SplFileInfo */ /** @var list<SplFileInfo> */
private array $teamcityFiles = []; private array $teamcityFiles = [];
/** @var SplFileInfo */ /** @var list<SplFileInfo> */
private array $testdoxFiles = []; private array $testdoxFiles = [];
/** @var non-empty-string[] */ /** @var non-empty-string[] */
@ -71,7 +73,7 @@ final class WrapperRunner implements RunnerInterface
$this->printer = new ResultPrinter($output, $options); $this->printer = new ResultPrinter($output, $options);
$wrapper = realpath( $wrapper = realpath(
dirname(__DIR__, 5) . DIRECTORY_SEPARATOR . 'bin' . DIRECTORY_SEPARATOR . 'phpunit-wrapper.php', dirname(__DIR__, 4) . DIRECTORY_SEPARATOR . 'bin' . DIRECTORY_SEPARATOR . 'pest-wrapper.php',
); );
assert($wrapper !== false); assert($wrapper !== false);
$phpFinder = new PhpExecutableFinder(); $phpFinder = new PhpExecutableFinder();
@ -89,21 +91,23 @@ final class WrapperRunner implements RunnerInterface
$this->parameters = $parameters; $this->parameters = $parameters;
} }
public function run(): void public function run(): int
{ {
ExcludeList::addDirectory(dirname(__DIR__)); ExcludeList::addDirectory(dirname(__DIR__));
TestResultFacade::init(); TestResultFacade::init();
EventFacade::seal(); EventFacade::seal();
$suiteLoader = new SuiteLoader($this->options, $this->output); $suiteLoader = new SuiteLoader($this->options, $this->output);
$this->pending = $this->getTestFiles($suiteLoader);
$result = TestResultFacade::result(); $result = TestResultFacade::result();
$this->pending = $suiteLoader->files;
$this->printer->setTestCount($suiteLoader->testCount); $this->printer->setTestCount($suiteLoader->testCount);
$this->printer->start(); $this->printer->start();
$this->startWorkers(); $this->startWorkers();
$this->assignAllPendingTests(); $this->assignAllPendingTests();
$this->waitForAllToFinish(); $this->waitForAllToFinish();
$this->complete($result);
return $this->complete($result);
} }
public function getExitCode(): int public function getExitCode(): int
@ -141,10 +145,7 @@ final class WrapperRunner implements RunnerInterface
if ( if (
$this->exitcode > 0 $this->exitcode > 0
&& ( && $this->options->configuration->stopOnFailure()
$this->options->configuration->stopOnFailure()
|| $this->options->configuration->stopOnError()
)
) { ) {
$this->pending = []; $this->pending = [];
} elseif (($pending = array_shift($this->pending)) !== null) { } elseif (($pending = array_shift($this->pending)) !== null) {
@ -160,7 +161,10 @@ final class WrapperRunner implements RunnerInterface
private function flushWorker(WrapperWorker $worker): void private function flushWorker(WrapperWorker $worker): void
{ {
$this->exitcode = max($this->exitcode, $worker->getExitCode()); $this->exitcode = max($this->exitcode, $worker->getExitCode());
$this->printer->printFeedback($worker->progressFile); $this->printer->printFeedback(
$worker->progressFile,
$this->teamcityFiles,
);
$worker->reset(); $worker->reset();
} }
@ -232,7 +236,7 @@ final class WrapperRunner implements RunnerInterface
unset($this->workers[$token]); unset($this->workers[$token]);
} }
private function complete(TestResult $testResultSum): void private function complete(TestResult $testResultSum): int
{ {
foreach ($this->testresultFiles as $testresultFile) { foreach ($this->testresultFiles as $testresultFile) {
if (! $testresultFile->isFile()) { if (! $testresultFile->isFile()) {
@ -251,6 +255,7 @@ final class WrapperRunner implements RunnerInterface
array_merge_recursive($testResultSum->testErroredEvents(), $testResult->testErroredEvents()), array_merge_recursive($testResultSum->testErroredEvents(), $testResult->testErroredEvents()),
array_merge_recursive($testResultSum->testFailedEvents(), $testResult->testFailedEvents()), array_merge_recursive($testResultSum->testFailedEvents(), $testResult->testFailedEvents()),
array_merge_recursive($testResultSum->testConsideredRiskyEvents(), $testResult->testConsideredRiskyEvents()), 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->testSkippedEvents(), $testResult->testSkippedEvents()),
array_merge_recursive($testResultSum->testMarkedIncompleteEvents(), $testResult->testMarkedIncompleteEvents()), array_merge_recursive($testResultSum->testMarkedIncompleteEvents(), $testResult->testMarkedIncompleteEvents()),
array_merge_recursive($testResultSum->testTriggeredDeprecationEvents(), $testResult->testTriggeredDeprecationEvents()), array_merge_recursive($testResultSum->testTriggeredDeprecationEvents(), $testResult->testTriggeredDeprecationEvents()),
@ -268,11 +273,15 @@ final class WrapperRunner implements RunnerInterface
); );
} }
$this->printer->printResults($testResultSum); $this->printer->printResults(
$testResultSum,
$this->teamcityFiles,
$this->testdoxFiles,
);
$this->generateCodeCoverageReports(); $this->generateCodeCoverageReports();
$this->generateLogs(); $this->generateLogs();
$this->exitcode = (new ShellExitCodeCalculator())->calculate( $exitcode = (new ShellExitCodeCalculator())->calculate(
$this->options->configuration->failOnEmptyTestSuite(), $this->options->configuration->failOnEmptyTestSuite(),
$this->options->configuration->failOnRisky(), $this->options->configuration->failOnRisky(),
$this->options->configuration->failOnWarning(), $this->options->configuration->failOnWarning(),
@ -280,6 +289,14 @@ final class WrapperRunner implements RunnerInterface
$this->options->configuration->failOnSkipped(), $this->options->configuration->failOnSkipped(),
$testResultSum, $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 protected function generateCodeCoverageReports(): void
@ -312,4 +329,33 @@ final class WrapperRunner implements RunnerInterface
$this->options->configuration->logfileJunit(), $this->options->configuration->logfileJunit(),
); );
} }
/** @param list<SplFileInfo> $files */
private function clearFiles(array $files): void
{
foreach ($files as $file) {
if (! $file->isFile()) {
continue;
}
unlink($file->getPathname());
}
}
private function getTestFiles(SuiteLoader $suiteLoader): array
{
/**
* TODO: Clean this up
*
* We are doing this because the SuiteLoader returns filenames incorrectly
* for Pest tests. We need to find a better way to do this.
*/
$tests = array_filter(
$suiteLoader->files,
fn(string $filename) => ! str_ends_with($filename, "eval()'d code")
);
return [...$tests, ...TestSuite::getInstance()->tests->getFilenames()];
}
} }