Skip to content

Commit

Permalink
Add full support to result cache (#919)
Browse files Browse the repository at this point in the history
  • Loading branch information
Slamdunk authored Dec 11, 2024
1 parent ae3c9f1 commit 4fb3f73
Show file tree
Hide file tree
Showing 11 changed files with 171 additions and 51 deletions.
9 changes: 6 additions & 3 deletions bin/phpunit-wrapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
'status-file:',
'progress-file:',
'unexpected-output-file:',
'testresult-file:',
'test-result-file:',
'result-cache-file:',
'teamcity-file:',
'testdox-file:',
'testdox-color',
Expand Down Expand Up @@ -40,7 +41,8 @@

assert(isset($getopt['progress-file']) && is_string($getopt['progress-file']));
assert(isset($getopt['unexpected-output-file']) && is_string($getopt['unexpected-output-file']));
assert(isset($getopt['testresult-file']) && is_string($getopt['testresult-file']));
assert(isset($getopt['test-result-file']) && is_string($getopt['test-result-file']));
assert(!isset($getopt['result-cache-file']) || is_string($getopt['result-cache-file']));
assert(!isset($getopt['teamcity-file']) || is_string($getopt['teamcity-file']));
assert(!isset($getopt['testdox-file']) || is_string($getopt['testdox-file']));
assert(!isset($getopt['testdox-columns']) || $getopt['testdox-columns'] === (string) (int) $getopt['testdox-columns']);
Expand All @@ -53,7 +55,8 @@
$phpunitArgv,
$getopt['progress-file'],
$getopt['unexpected-output-file'],
$getopt['testresult-file'],
$getopt['test-result-file'],
$getopt['result-cache-file'] ?? null,
$getopt['teamcity-file'] ?? null,
$getopt['testdox-file'] ?? null,
isset($getopt['testdox-color']),
Expand Down
6 changes: 3 additions & 3 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,12 @@
"ext-simplexml": "*",
"fidry/cpu-core-counter": "^1.2.0",
"jean85/pretty-package-versions": "^2.1.0",
"phpunit/php-code-coverage": "^11.0.7",
"phpunit/php-code-coverage": "^11.0.8",
"phpunit/php-file-iterator": "^5.1.0",
"phpunit/php-timer": "^7.0.1",
"phpunit/phpunit": "^11.5.0",
"phpunit/phpunit": "^11.5.1",
"sebastian/environment": "^7.2.0",
"symfony/console": "^6.4.14 || ^7.2.0",
"symfony/console": "^6.4.14 || ^7.2.1",
"symfony/process": "^6.4.14 || ^7.2.0"
},
"require-dev": {
Expand Down
30 changes: 12 additions & 18 deletions phpstan-baseline.neon
Original file line number Diff line number Diff line change
Expand Up @@ -30,24 +30,6 @@ parameters:
count: 1
path: src/Options.php

-
message: '#^Call to an undefined method PHPUnit\\Metadata\\Api\\CodeCoverage\:\:linesToBeIgnored\(\)\.$#'
identifier: method.notFound
count: 1
path: src/WrapperRunner/ApplicationForWrapperWorker.php

-
message: '#^Call to an undefined method PHPUnit\\Runner\\Filter\\Factory\:\:addNameFilter\(\)\.$#'
identifier: method.notFound
count: 1
path: src/WrapperRunner/ApplicationForWrapperWorker.php

-
message: '#^Parameter \#1 \$linesToBeIgnored of method PHPUnit\\Runner\\CodeCoverage\:\:ignoreLines\(\) expects array\<string, list\<int\>\>, mixed given\.$#'
identifier: argument.type
count: 1
path: src/WrapperRunner/ApplicationForWrapperWorker.php

-
message: '#^Match expression does not handle remaining value\: string$#'
identifier: match.unhandled
Expand Down Expand Up @@ -186,6 +168,12 @@ parameters:
count: 2
path: src/WrapperRunner/WrapperWorker.php

-
message: '#^Access to an uninitialized readonly property ParaTest\\WrapperRunner\\WrapperWorker\:\:\$resultCacheFile\.$#'
identifier: property.uninitializedReadonly
count: 2
path: src/WrapperRunner/WrapperWorker.php

-
message: '#^Access to an uninitialized readonly property ParaTest\\WrapperRunner\\WrapperWorker\:\:\$teamcityFile\.$#'
identifier: property.uninitializedReadonly
Expand All @@ -210,6 +198,12 @@ parameters:
count: 1
path: src/WrapperRunner/WrapperWorker.php

-
message: '#^Class ParaTest\\WrapperRunner\\WrapperWorker has an uninitialized readonly property \$resultCacheFile\. Assign it in the constructor\.$#'
identifier: property.uninitializedReadonly
count: 1
path: src/WrapperRunner/WrapperWorker.php

-
message: '#^Class ParaTest\\WrapperRunner\\WrapperWorker has an uninitialized readonly property \$teamcityFile\. Assign it in the constructor\.$#'
identifier: property.uninitializedReadonly
Expand Down
31 changes: 13 additions & 18 deletions src/WrapperRunner/ApplicationForWrapperWorker.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
use PHPUnit\Logging\JUnit\JunitXmlLogger;
use PHPUnit\Logging\TeamCity\TeamCityLogger;
use PHPUnit\Logging\TestDox\TestResultCollector;
use PHPUnit\Metadata\Api\CodeCoverage as CodeCoverageMetadataApi;
use PHPUnit\Runner\Baseline\CannotLoadBaselineException;
use PHPUnit\Runner\Baseline\Reader;
use PHPUnit\Runner\CodeCoverage;
Expand All @@ -21,9 +20,10 @@
use PHPUnit\Runner\Extension\Facade as ExtensionFacade;
use PHPUnit\Runner\Extension\PharLoader;
use PHPUnit\Runner\Filter\Factory;
use PHPUnit\Runner\ResultCache\DefaultResultCache;
use PHPUnit\Runner\ResultCache\ResultCacheHandler;
use PHPUnit\Runner\TestSuiteLoader;
use PHPUnit\Runner\TestSuiteSorter;
use PHPUnit\Runner\Version;
use PHPUnit\TestRunner\IssueFilter;
use PHPUnit\TestRunner\TestResult\Facade as TestResultFacade;
use PHPUnit\TextUI\Configuration\Builder;
Expand All @@ -46,7 +46,6 @@
use function str_ends_with;
use function strpos;
use function substr;
use function version_compare;

/**
* @internal
Expand All @@ -64,7 +63,8 @@ public function __construct(
private readonly array $argv,
private readonly string $progressFile,
private readonly string $unexpectedOutputFile,
private readonly string $testresultFile,
private readonly string $testResultFile,
private readonly ?string $resultCacheFile,
private readonly ?string $teamcityFile,
private readonly ?string $testdoxFile,
private readonly bool $testdoxColor,
Expand All @@ -80,11 +80,7 @@ public function runTest(string $testPath): int
$filter = new Factory();
$name = substr($testPath, $null + 1);
assert($name !== '');
if (version_compare(Version::id(), '11.0.0') >= 0) {
$filter->addIncludeNameFilter($name);
} else {
$filter->addNameFilter($name);
}
$filter->addIncludeNameFilter($name);

$testPath = substr($testPath, 0, $null);
}
Expand All @@ -99,14 +95,6 @@ public function runTest(string $testPath): int
$testSuite = TestSuite::fromClassReflector($testSuiteRefl);
}

if (version_compare(Version::id(), '11.0.0') < 0) {
if (CodeCoverage::instance()->isActive()) {
CodeCoverage::instance()->ignoreLines(
(new CodeCoverageMetadataApi())->linesToBeIgnored($testSuite),
);
}
}

(new TestSuiteFilterProcessor())->process($this->configuration, $testSuite);

if ($filter !== null) {
Expand Down Expand Up @@ -209,6 +197,13 @@ private function bootstrap(): void
TestResultFacade::init();
DeprecationCollector::init();

if (isset($this->resultCacheFile)) {
new ResultCacheHandler(
new DefaultResultCache($this->resultCacheFile),
EventFacade::instance(),
);
}

if ($this->configuration->source()->useBaseline()) {
$baselineFile = $this->configuration->source()->baseline();
$baseline = null;
Expand Down Expand Up @@ -262,7 +257,7 @@ public function end(): void
);
}

file_put_contents($this->testresultFile, serialize($result));
file_put_contents($this->testResultFile, serialize($result));

EventFacade::emitter()->applicationFinished(0);
}
Expand Down
9 changes: 8 additions & 1 deletion src/WrapperRunner/SuiteLoader.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
use PHPUnit\Runner\Extension\Facade as ExtensionFacade;
use PHPUnit\Runner\Extension\PharLoader;
use PHPUnit\Runner\PhptTestCase;
use PHPUnit\Runner\ResultCache\DefaultResultCache;
use PHPUnit\Runner\ResultCache\NullResultCache;
use PHPUnit\Runner\TestSuiteSorter;
use PHPUnit\TestRunner\TestResult\Facade as TestResultFacade;
Expand Down Expand Up @@ -95,7 +96,13 @@ public function __construct(
$this->options->configuration->executionOrderDefects() !== TestSuiteSorter::ORDER_DEFAULT ||
$this->options->configuration->resolveDependencies()
) {
(new TestSuiteSorter(new NullResultCache()))->reorderTestsInSuite(
$resultCache = new NullResultCache();
if ($this->options->configuration->cacheResult()) {
$resultCache = new DefaultResultCache($this->options->configuration->testResultCacheFile());
$resultCache->load();
}

(new TestSuiteSorter($resultCache))->reorderTestsInSuite(
$testSuite,
$this->options->configuration->executionOrder(),
$this->options->configuration->resolveDependencies(),
Expand Down
28 changes: 24 additions & 4 deletions src/WrapperRunner/WrapperRunner.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use ParaTest\Options;
use ParaTest\RunnerInterface;
use PHPUnit\Runner\CodeCoverage;
use PHPUnit\Runner\ResultCache\DefaultResultCache;
use PHPUnit\TestRunner\TestResult\Facade as TestResultFacade;
use PHPUnit\TestRunner\TestResult\TestResult;
use PHPUnit\TextUI\Configuration\CodeCoverageFilterRegistry;
Expand Down Expand Up @@ -55,7 +56,9 @@ final class WrapperRunner implements RunnerInterface
/** @var list<SplFileInfo> */
private array $unexpectedOutputFiles = [];
/** @var list<SplFileInfo> */
private array $testresultFiles = [];
private array $resultCacheFiles = [];
/** @var list<SplFileInfo> */
private array $testResultFiles = [];
/** @var list<SplFileInfo> */
private array $coverageFiles = [];
/** @var list<SplFileInfo> */
Expand Down Expand Up @@ -211,7 +214,11 @@ private function startWorker(int $token): WrapperWorker
$this->statusFiles[] = $worker->statusFile;
$this->progressFiles[] = $worker->progressFile;
$this->unexpectedOutputFiles[] = $worker->unexpectedOutputFile;
$this->testresultFiles[] = $worker->testresultFile;
$this->testResultFiles[] = $worker->testResultFile;

if (isset($worker->resultCacheFile)) {
$this->resultCacheFiles[] = $worker->resultCacheFile;
}

if (isset($worker->junitFile)) {
$this->junitFiles[] = $worker->junitFile;
Expand Down Expand Up @@ -245,7 +252,7 @@ private function destroyWorker(int $token): void

private function complete(TestResult $testResultSum): int
{
foreach ($this->testresultFiles as $testresultFile) {
foreach ($this->testResultFiles as $testresultFile) {
if (! $testresultFile->isFile()) {
continue;
}
Expand Down Expand Up @@ -281,6 +288,18 @@ private function complete(TestResult $testResultSum): int
);
}

if ($this->options->configuration->cacheResult()) {
$resultCacheSum = new DefaultResultCache($this->options->configuration->testResultCacheFile());
foreach ($this->resultCacheFiles as $resultCacheFile) {
$resultCache = new DefaultResultCache($resultCacheFile->getPathname());
$resultCache->load();

$resultCacheSum->mergeWith($resultCache);
}

$resultCacheSum->persist();
}

$this->printer->printResults(
$testResultSum,
$this->teamcityFiles,
Expand All @@ -304,7 +323,8 @@ private function complete(TestResult $testResultSum): int
$this->clearFiles($this->statusFiles);
$this->clearFiles($this->progressFiles);
$this->clearFiles($this->unexpectedOutputFiles);
$this->clearFiles($this->testresultFiles);
$this->clearFiles($this->testResultFiles);
$this->clearFiles($this->resultCacheFiles);
$this->clearFiles($this->coverageFiles);
$this->clearFiles($this->junitFiles);
$this->clearFiles($this->teamcityFiles);
Expand Down
20 changes: 16 additions & 4 deletions src/WrapperRunner/WrapperWorker.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ final class WrapperWorker
public readonly SplFileInfo $statusFile;
public readonly SplFileInfo $progressFile;
public readonly SplFileInfo $unexpectedOutputFile;
public readonly SplFileInfo $testresultFile;
public readonly SplFileInfo $testResultFile;
public readonly SplFileInfo $resultCacheFile;
public readonly SplFileInfo $junitFile;
public readonly SplFileInfo $coverageFile;
public readonly SplFileInfo $teamcityFile;
Expand Down Expand Up @@ -66,7 +67,12 @@ public function __construct(
touch($this->progressFile->getPathname());
$this->unexpectedOutputFile = new SplFileInfo($commonTmpFilePath . 'unexpected_output');
touch($this->unexpectedOutputFile->getPathname());
$this->testresultFile = new SplFileInfo($commonTmpFilePath . 'testresult');
$this->testResultFile = new SplFileInfo($commonTmpFilePath . 'test_result');

if ($this->options->configuration->cacheResult()) {
$this->resultCacheFile = new SplFileInfo($commonTmpFilePath . 'result_cache');
}

if ($options->configuration->hasLogfileJunit()) {
$this->junitFile = new SplFileInfo($commonTmpFilePath . 'junit');
}
Expand All @@ -89,8 +95,14 @@ public function __construct(
$parameters[] = $this->progressFile->getPathname();
$parameters[] = '--unexpected-output-file';
$parameters[] = $this->unexpectedOutputFile->getPathname();
$parameters[] = '--testresult-file';
$parameters[] = $this->testresultFile->getPathname();
$parameters[] = '--test-result-file';
$parameters[] = $this->testResultFile->getPathname();

if (isset($this->resultCacheFile)) {
$parameters[] = '--result-cache-file';
$parameters[] = $this->resultCacheFile->getPathname();
}

if (isset($this->teamcityFile)) {
$parameters[] = '--teamcity-file';
$parameters[] = $this->teamcityFile->getPathname();
Expand Down
46 changes: 46 additions & 0 deletions test/Unit/WrapperRunner/WrapperRunnerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
use function file_put_contents;
use function glob;
use function implode;
use function is_file;
use function min;
use function posix_mkfifo;
use function preg_match;
Expand Down Expand Up @@ -805,6 +806,51 @@ public function testExtensionMustRunBeforeDataProvider(): void
self::assertEquals(RunnerInterface::SUCCESS_EXIT, $runnerResult->exitCode);
}

public function testOrderByCache(): void
{
$resultCacheFile = $this->fixture('order_by') . DIRECTORY_SEPARATOR . '.phpunit.result.cache';
if (is_file($resultCacheFile)) {
unlink($resultCacheFile);
}

$this->bareOptions['--configuration'] = $this->fixture('order_by' . DIRECTORY_SEPARATOR . 'phpunit.xml');
$this->bareOptions['--processes'] = '1';
$this->bareOptions['--order-by'] = 'defects';

$expectedOutput = static function (string $order): string {
return 'Processes: %s
Runtime: PHP %s
Configuration: %s
' . $order . ' 2 / 2 (100%)
Time: %s, Memory: %s MB
There was 1 failure:
1) ParaTest\Tests\fixtures\order_by\BFailingTest::testFailure
Failed asserting that false is true.
%s/test/fixtures/order_by/BFailingTest.php:14
FAILURES!
%s
';
};

$runnerResult = $this->runRunner();

self::assertStringMatchesFormat($expectedOutput('.F'), $runnerResult->output);
self::assertEquals(RunnerInterface::FAILURE_EXIT, $runnerResult->exitCode);

self::assertFileExists($resultCacheFile);

$runnerResult = $this->runRunner();

self::assertStringMatchesFormat($expectedOutput('F.'), $runnerResult->output);
self::assertEquals(RunnerInterface::FAILURE_EXIT, $runnerResult->exitCode);
}

/**
* ### WARNING ###
*
Expand Down
16 changes: 16 additions & 0 deletions test/fixtures/order_by/ASuccessfulTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

declare(strict_types=1);

namespace ParaTest\Tests\fixtures\order_by;

use PHPUnit\Framework\TestCase;

/** @internal */
final class ASuccessfulTest extends TestCase
{
public function testSuccess(): void
{
$this->assertTrue(true);
}
}
Loading

0 comments on commit 4fb3f73

Please sign in to comment.