Skip to content

Commit 0182206

Browse files
staabmsebastianbergmann
authored andcommitted
Introduce ResultCacheId
1 parent 5984c2c commit 0182206

File tree

10 files changed

+169
-62
lines changed

10 files changed

+169
-62
lines changed

src/Runner/ResultCache/DefaultResultCache.php

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -63,28 +63,28 @@ public function __construct(?string $filepath = null)
6363
$this->cacheFilename = $filepath ?? $_ENV['PHPUNIT_RESULT_CACHE'] ?? self::DEFAULT_RESULT_CACHE_FILENAME;
6464
}
6565

66-
public function setStatus(string $id, TestStatus $status): void
66+
public function setStatus(ResultCacheId $id, TestStatus $status): void
6767
{
6868
if ($status->isSuccess()) {
6969
return;
7070
}
7171

72-
$this->defects[$id] = $status;
72+
$this->defects[$id->asString()] = $status;
7373
}
7474

75-
public function status(string $id): TestStatus
75+
public function status(ResultCacheId $id): TestStatus
7676
{
77-
return $this->defects[$id] ?? TestStatus::unknown();
77+
return $this->defects[$id->asString()] ?? TestStatus::unknown();
7878
}
7979

80-
public function setTime(string $id, float $time): void
80+
public function setTime(ResultCacheId $id, float $time): void
8181
{
82-
$this->times[$id] = $time;
82+
$this->times[$id->asString()] = $time;
8383
}
8484

85-
public function time(string $id): float
85+
public function time(ResultCacheId $id): float
8686
{
87-
return $this->times[$id] ?? 0.0;
87+
return $this->times[$id->asString()] ?? 0.0;
8888
}
8989

9090
public function mergeWith(self $other): void

src/Runner/ResultCache/NullResultCache.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,20 +18,20 @@
1818
*/
1919
final readonly class NullResultCache implements ResultCache
2020
{
21-
public function setStatus(string $id, TestStatus $status): void
21+
public function setStatus(ResultCacheId $id, TestStatus $status): void
2222
{
2323
}
2424

25-
public function status(string $id): TestStatus
25+
public function status(ResultCacheId $id): TestStatus
2626
{
2727
return TestStatus::unknown();
2828
}
2929

30-
public function setTime(string $id, float $time): void
30+
public function setTime(ResultCacheId $id, float $time): void
3131
{
3232
}
3333

34-
public function time(string $id): float
34+
public function time(ResultCacheId $id): float
3535
{
3636
return 0;
3737
}

src/Runner/ResultCache/ResultCache.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,13 @@
1818
*/
1919
interface ResultCache
2020
{
21-
public function setStatus(string $id, TestStatus $status): void;
21+
public function setStatus(ResultCacheId $id, TestStatus $status): void;
2222

23-
public function status(string $id): TestStatus;
23+
public function status(ResultCacheId $id): TestStatus;
2424

25-
public function setTime(string $id, float $time): void;
25+
public function setTime(ResultCacheId $id, float $time): void;
2626

27-
public function time(string $id): float;
27+
public function time(ResultCacheId $id): float;
2828

2929
public function load(): void;
3030

src/Runner/ResultCache/ResultCacheHandler.php

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -69,31 +69,31 @@ public function testPrepared(Prepared $event): void
6969
public function testMarkedIncomplete(MarkedIncomplete $event): void
7070
{
7171
$this->cache->setStatus(
72-
$event->test()->id(),
72+
ResultCacheId::fromTest($event->test()),
7373
TestStatus::incomplete($event->throwable()->message()),
7474
);
7575
}
7676

7777
public function testConsideredRisky(ConsideredRisky $event): void
7878
{
7979
$this->cache->setStatus(
80-
$event->test()->id(),
80+
ResultCacheId::fromTest($event->test()),
8181
TestStatus::risky($event->message()),
8282
);
8383
}
8484

8585
public function testErrored(Errored $event): void
8686
{
8787
$this->cache->setStatus(
88-
$event->test()->id(),
88+
ResultCacheId::fromTest($event->test()),
8989
TestStatus::error($event->throwable()->message()),
9090
);
9191
}
9292

9393
public function testFailed(Failed $event): void
9494
{
9595
$this->cache->setStatus(
96-
$event->test()->id(),
96+
ResultCacheId::fromTest($event->test()),
9797
TestStatus::failure($event->throwable()->message()),
9898
);
9999
}
@@ -105,11 +105,11 @@ public function testFailed(Failed $event): void
105105
public function testSkipped(Skipped $event): void
106106
{
107107
$this->cache->setStatus(
108-
$event->test()->id(),
108+
ResultCacheId::fromTest($event->test()),
109109
TestStatus::skipped($event->message()),
110110
);
111111

112-
$this->cache->setTime($event->test()->id(), $this->duration($event));
112+
$this->cache->setTime(ResultCacheId::fromTest($event->test()), $this->duration($event));
113113
}
114114

115115
/**
@@ -118,7 +118,7 @@ public function testSkipped(Skipped $event): void
118118
*/
119119
public function testFinished(Finished $event): void
120120
{
121-
$this->cache->setTime($event->test()->id(), $this->duration($event));
121+
$this->cache->setTime(ResultCacheId::fromTest($event->test()), $this->duration($event));
122122

123123
$this->time = null;
124124
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
<?php declare(strict_types=1);
2+
/*
3+
* This file is part of PHPUnit.
4+
*
5+
* (c) Sebastian Bergmann <[email protected]>
6+
*
7+
* For the full copyright and license information, please view the LICENSE
8+
* file that was distributed with this source code.
9+
*/
10+
namespace PHPUnit\Runner\ResultCache;
11+
12+
use PHPUnit\Event\Code\Test;
13+
use PHPUnit\Framework\Reorderable;
14+
use PHPUnit\Framework\TestCase;
15+
16+
/**
17+
* @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
18+
*
19+
* @internal This class is not covered by the backward compatibility promise for PHPUnit
20+
*/
21+
final readonly class ResultCacheId
22+
{
23+
public static function fromTest(Test $test): self
24+
{
25+
return new self($test->id());
26+
}
27+
28+
public static function fromReorderable(Reorderable $reorderable): self
29+
{
30+
return new self($reorderable->sortId());
31+
}
32+
33+
/**
34+
* For use in PHPUnit tests only!
35+
*
36+
* @param class-string<TestCase> $class
37+
*/
38+
public static function fromTestClassAndMethodName(string $class, string $methodName): self
39+
{
40+
return new self($class . '::' . $methodName);
41+
}
42+
43+
private function __construct(
44+
private string $id,
45+
) {
46+
}
47+
48+
public function asString(): string
49+
{
50+
return $this->id;
51+
}
52+
}

src/Runner/TestSuiteSorter.php

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
use PHPUnit\Framework\TestSuite;
2626
use PHPUnit\Runner\ResultCache\NullResultCache;
2727
use PHPUnit\Runner\ResultCache\ResultCache;
28+
use PHPUnit\Runner\ResultCache\ResultCacheId;
2829

2930
/**
3031
* @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
@@ -192,9 +193,11 @@ private function addSuiteToDefectSortOrder(TestSuite $suite): void
192193
continue;
193194
}
194195

195-
if (!isset($this->defectSortOrder[$test->sortId()])) {
196-
$this->defectSortOrder[$test->sortId()] = $this->cache->status($test->sortId())->asInt();
197-
$max = max($max, $this->defectSortOrder[$test->sortId()]);
196+
$sortId = $test->sortId();
197+
198+
if (!isset($this->defectSortOrder[$sortId])) {
199+
$this->defectSortOrder[$sortId] = $this->cache->status(ResultCacheId::fromReorderable($test))->asInt();
200+
$max = max($max, $this->defectSortOrder[$sortId]);
198201
}
199202
}
200203

@@ -306,7 +309,7 @@ private function cmpDuration(Test $a, Test $b): int
306309
return 0;
307310
}
308311

309-
return $this->cache->time($a->sortId()) <=> $this->cache->time($b->sortId());
312+
return $this->cache->time(ResultCacheId::fromReorderable($a)) <=> $this->cache->time(ResultCacheId::fromReorderable($b));
310313
}
311314

312315
/**

tests/unit/Runner/ResultCache/DefaultResultCacheTest.php

Lines changed: 29 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ final class DefaultResultCacheTest extends TestCase
2525
{
2626
public function testGetTimeForNonExistentTestNameReturnsFloatZero(): void
2727
{
28-
$this->assertSame(0.0, (new DefaultResultCache)->time('doesNotExist'));
28+
$this->assertSame(0.0, (new DefaultResultCache)->time(ResultCacheId::fromTestClassAndMethodName(self::class, 'doesNotExist')));
2929
}
3030

3131
public function testReadsCacheFromProvidedFilename(): void
@@ -34,66 +34,67 @@ public function testReadsCacheFromProvidedFilename(): void
3434
$cache = new DefaultResultCache($cacheFile);
3535
$cache->load();
3636

37-
$this->assertTrue($cache->status(MultiDependencyTest::class . '::testOne')->isUnknown());
38-
$this->assertTrue($cache->status(MultiDependencyTest::class . '::testFive')->isSkipped());
37+
$this->assertTrue($cache->status(ResultCacheId::fromTestClassAndMethodName(MultiDependencyTest::class, 'testOne'))->isUnknown());
38+
$this->assertTrue($cache->status(ResultCacheId::fromTestClassAndMethodName(MultiDependencyTest::class, 'testFive'))->isSkipped());
3939
}
4040

4141
public function testDoesClearCacheBeforeLoad(): void
4242
{
43-
$cacheFile = TEST_FILES_PATH . '../end-to-end/execution-order/_files/MultiDependencyTest_result_cache.txt';
44-
$cache = new DefaultResultCache($cacheFile);
45-
$cache->setStatus('someTest', TestStatus::failure());
43+
$cacheFile = TEST_FILES_PATH . '../end-to-end/execution-order/_files/MultiDependencyTest_result_cache.txt';
44+
$cache = new DefaultResultCache($cacheFile);
45+
$resultCacheId = ResultCacheId::fromTestClassAndMethodName(self::class, 'someTest');
46+
$cache->setStatus($resultCacheId, TestStatus::failure());
4647

47-
$this->assertTrue($cache->status(MultiDependencyTest::class . '::testFive')->isUnknown());
48+
$this->assertTrue($cache->status(ResultCacheId::fromTestClassAndMethodName(MultiDependencyTest::class, 'testFive'))->isUnknown());
4849

4950
$cache->load();
5051

51-
$this->assertTrue($cache->status(MultiDependencyTest::class . '::someTest')->isUnknown());
52-
$this->assertTrue($cache->status(MultiDependencyTest::class . '::testFive')->isSkipped());
52+
$this->assertTrue($cache->status(ResultCacheId::fromTestClassAndMethodName(MultiDependencyTest::class, 'someTest'))->isUnknown());
53+
$this->assertTrue($cache->status(ResultCacheId::fromTestClassAndMethodName(MultiDependencyTest::class, 'testFive'))->isSkipped());
5354
}
5455

5556
public function testCanPersistCacheToFile(): void
5657
{
57-
$cacheFile = tempnam(sys_get_temp_dir(), 'phpunit_');
58-
$cache = new DefaultResultCache($cacheFile);
59-
$testName = 'test' . uniqid('', true);
58+
$cacheFile = tempnam(sys_get_temp_dir(), 'phpunit_');
59+
$cache = new DefaultResultCache($cacheFile);
60+
$resultCacheId = ResultCacheId::fromTestClassAndMethodName(self::class, 'test' . uniqid('', true));
6061

61-
$cache->setStatus($testName, TestStatus::skipped());
62+
$cache->setStatus($resultCacheId, TestStatus::skipped());
6263
$cache->persist();
6364

6465
$cache = new DefaultResultCache($cacheFile);
6566
$cache->load();
6667

67-
$this->assertTrue($cache->status($testName)->isSkipped());
68+
$this->assertTrue($cache->status($resultCacheId)->isSkipped());
6869

6970
unlink($cacheFile);
7071
}
7172

7273
public function testCanBeMerged(): void
7374
{
7475
$cacheSourceOne = new DefaultResultCache;
75-
$cacheSourceOne->setStatus('status.a', TestStatus::skipped());
76-
$cacheSourceOne->setStatus('status.b', TestStatus::incomplete());
77-
$cacheSourceOne->setTime('time.a', 1);
78-
$cacheSourceOne->setTime('time.b', 2);
76+
$cacheSourceOne->setStatus(ResultCacheId::fromTestClassAndMethodName(self::class, 'status.a'), TestStatus::skipped());
77+
$cacheSourceOne->setStatus(ResultCacheId::fromTestClassAndMethodName(self::class, 'status.b'), TestStatus::incomplete());
78+
$cacheSourceOne->setTime(ResultCacheId::fromTestClassAndMethodName(self::class, 'time.a'), 1);
79+
$cacheSourceOne->setTime(ResultCacheId::fromTestClassAndMethodName(self::class, 'time.b'), 2);
7980
$cacheSourceTwo = new DefaultResultCache;
80-
$cacheSourceTwo->setStatus('status.c', TestStatus::failure());
81-
$cacheSourceTwo->setTime('time.c', 4);
81+
$cacheSourceTwo->setStatus(ResultCacheId::fromTestClassAndMethodName(self::class, 'status.c'), TestStatus::failure());
82+
$cacheSourceTwo->setTime(ResultCacheId::fromTestClassAndMethodName(self::class, 'time.c'), 4);
8283

8384
$sum = new DefaultResultCache;
8485
$sum->mergeWith($cacheSourceOne);
8586

86-
$this->assertSame(TestStatus::skipped()->asString(), $sum->status('status.a')->asString());
87-
$this->assertSame(TestStatus::incomplete()->asString(), $sum->status('status.b')->asString());
88-
$this->assertNotSame(TestStatus::failure()->asString(), $sum->status('status.c')->asString());
87+
$this->assertSame(TestStatus::skipped()->asString(), $sum->status(ResultCacheId::fromTestClassAndMethodName(self::class, 'status.a'))->asString());
88+
$this->assertSame(TestStatus::incomplete()->asString(), $sum->status(ResultCacheId::fromTestClassAndMethodName(self::class, 'status.b'))->asString());
89+
$this->assertNotSame(TestStatus::failure()->asString(), $sum->status(ResultCacheId::fromTestClassAndMethodName(self::class, 'status.c'))->asString());
8990

90-
$this->assertSame(1.0, $sum->time('time.a'));
91-
$this->assertSame(2.0, $sum->time('time.b'));
92-
$this->assertNotSame(4.0, $sum->time('time.c'));
91+
$this->assertSame(1.0, $sum->time(ResultCacheId::fromTestClassAndMethodName(self::class, 'time.a')));
92+
$this->assertSame(2.0, $sum->time(ResultCacheId::fromTestClassAndMethodName(self::class, 'time.b')));
93+
$this->assertNotSame(4.0, $sum->time(ResultCacheId::fromTestClassAndMethodName(self::class, 'time.c')));
9394

9495
$sum->mergeWith($cacheSourceTwo);
9596

96-
$this->assertSame(TestStatus::failure()->asString(), $sum->status('status.c')->asString());
97-
$this->assertSame(4.0, $sum->time('time.c'));
97+
$this->assertSame(TestStatus::failure()->asString(), $sum->status(ResultCacheId::fromTestClassAndMethodName(self::class, 'status.c'))->asString());
98+
$this->assertSame(4.0, $sum->time(ResultCacheId::fromTestClassAndMethodName(self::class, 'time.c')));
9899
}
99100
}

tests/unit/Runner/ResultCache/NullTestResultCacheTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ public function testHasWorkingStubs(): void
2323
$cache->load();
2424
$cache->persist();
2525

26-
$this->assertTrue($cache->status('testName')->isUnknown());
27-
$this->assertSame(0.0, $cache->time('testName'));
26+
$this->assertTrue($cache->status(ResultCacheId::fromTestClassAndMethodName(self::class, 'testName'))->isUnknown());
27+
$this->assertSame(0.0, $cache->time(ResultCacheId::fromTestClassAndMethodName(self::class, 'testName')));
2828
}
2929
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
<?php declare(strict_types=1);
2+
/*
3+
* This file is part of PHPUnit.
4+
*
5+
* (c) Sebastian Bergmann <[email protected]>
6+
*
7+
* For the full copyright and license information, please view the LICENSE
8+
* file that was distributed with this source code.
9+
*/
10+
namespace PHPUnit\Runner\ResultCache;
11+
12+
use PHPUnit\Event\Code\TestDox;
13+
use PHPUnit\Event\Code\TestMethod;
14+
use PHPUnit\Event\TestData\TestDataCollection;
15+
use PHPUnit\Framework\Attributes\CoversClass;
16+
use PHPUnit\Framework\Attributes\DataProvider;
17+
use PHPUnit\Framework\Attributes\Small;
18+
use PHPUnit\Framework\TestCase;
19+
use PHPUnit\Metadata\MetadataCollection;
20+
21+
#[CoversClass(DefaultResultCache::class)]
22+
#[Small]
23+
final class ResultCacheIdTest extends TestCase
24+
{
25+
public static function provideResultCacheIds(): iterable
26+
{
27+
yield ['PHPUnit\Runner\ResultCache\ResultCacheIdTest::a method', ResultCacheId::fromTestClassAndMethodName(self::class, 'a method')];
28+
29+
yield ['PHPUnit\Runner\ResultCache\ResultCacheIdTest::testMethod', ResultCacheId::fromTest(self::testMethod())];
30+
}
31+
32+
#[DataProvider('provideResultCacheIds')]
33+
public function testResultCacheId($expectedString, ResultCacheId $cacheId): void
34+
{
35+
$this->assertSame($expectedString, $cacheId->asString());
36+
}
37+
38+
private static function testMethod(): TestMethod
39+
{
40+
return new TestMethod(
41+
self::class,
42+
'testMethod',
43+
'TestClass.php',
44+
1,
45+
new TestDox('', '', ''),
46+
MetadataCollection::fromArray([]),
47+
TestDataCollection::fromArray([]),
48+
);
49+
}
50+
}

0 commit comments

Comments
 (0)