Skip to content

Commit be5f915

Browse files
authored
Merge pull request #420 from ergebnis/feature/phase
Enhancement: Implement `PhaseStart` and `Phase`
2 parents 4bf3753 + a69cf35 commit be5f915

File tree

12 files changed

+446
-46
lines changed

12 files changed

+446
-46
lines changed
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/**
6+
* Copyright (c) 2021-2023 Andreas Möller
7+
*
8+
* For the full copyright and license information, please view
9+
* the LICENSE.md file that was distributed with this source code.
10+
*
11+
* @see https://github.com/ergebnis/phpunit-slow-test-detector
12+
*/
13+
14+
namespace Ergebnis\PHPUnit\SlowTestDetector\Exception;
15+
16+
/**
17+
* @internal
18+
*/
19+
final class InvalidPhaseIdentifier extends \InvalidArgumentException
20+
{
21+
public static function blankOrEmpty(): self
22+
{
23+
return new self('Value can not be blank or empty.');
24+
}
25+
}

src/Phase.php

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/**
6+
* Copyright (c) 2021-2023 Andreas Möller
7+
*
8+
* For the full copyright and license information, please view
9+
* the LICENSE.md file that was distributed with this source code.
10+
*
11+
* @see https://github.com/ergebnis/phpunit-slow-test-detector
12+
*/
13+
14+
namespace Ergebnis\PHPUnit\SlowTestDetector;
15+
16+
/**
17+
* @internal
18+
*/
19+
final class Phase
20+
{
21+
private PhaseIdentifier $phaseIdentifier;
22+
private Time $startTime;
23+
private Time $stopTime;
24+
private Duration $duration;
25+
26+
private function __construct(
27+
PhaseIdentifier $phaseIdentifier,
28+
Time $startTime,
29+
Time $stopTime,
30+
Duration $duration
31+
) {
32+
$this->phaseIdentifier = $phaseIdentifier;
33+
$this->startTime = $startTime;
34+
$this->stopTime = $stopTime;
35+
$this->duration = $duration;
36+
}
37+
38+
public static function create(
39+
PhaseIdentifier $phaseIdentifier,
40+
Time $startTime,
41+
Time $stopTime
42+
): self {
43+
return new self(
44+
$phaseIdentifier,
45+
$startTime,
46+
$stopTime,
47+
$stopTime->duration($startTime),
48+
);
49+
}
50+
51+
public function phaseIdentifier(): PhaseIdentifier
52+
{
53+
return $this->phaseIdentifier;
54+
}
55+
56+
public function startTime(): Time
57+
{
58+
return $this->startTime;
59+
}
60+
61+
public function stopTime(): Time
62+
{
63+
return $this->stopTime;
64+
}
65+
66+
public function duration(): Duration
67+
{
68+
return $this->duration;
69+
}
70+
}

src/PhaseIdentifier.php

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/**
6+
* Copyright (c) 2021-2023 Andreas Möller
7+
*
8+
* For the full copyright and license information, please view
9+
* the LICENSE.md file that was distributed with this source code.
10+
*
11+
* @see https://github.com/ergebnis/phpunit-slow-test-detector
12+
*/
13+
14+
namespace Ergebnis\PHPUnit\SlowTestDetector;
15+
16+
/**
17+
* @internal
18+
*/
19+
final class PhaseIdentifier
20+
{
21+
private string $value;
22+
23+
private function __construct(string $value)
24+
{
25+
$this->value = $value;
26+
}
27+
28+
/**
29+
* @throws Exception\InvalidPhaseIdentifier
30+
*/
31+
public static function fromString(string $value): self
32+
{
33+
if ('' === \trim($value)) {
34+
throw Exception\InvalidPhaseIdentifier::blankOrEmpty();
35+
}
36+
37+
return new self($value);
38+
}
39+
40+
public function toString(): string
41+
{
42+
return $this->value;
43+
}
44+
}

src/PhaseStart.php

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/**
6+
* Copyright (c) 2021-2023 Andreas Möller
7+
*
8+
* For the full copyright and license information, please view
9+
* the LICENSE.md file that was distributed with this source code.
10+
*
11+
* @see https://github.com/ergebnis/phpunit-slow-test-detector
12+
*/
13+
14+
namespace Ergebnis\PHPUnit\SlowTestDetector;
15+
16+
/**
17+
* @internal
18+
*/
19+
final class PhaseStart
20+
{
21+
private PhaseIdentifier $phaseIdentifier;
22+
private Time $startTime;
23+
24+
private function __construct(
25+
PhaseIdentifier $phaseIdentifier,
26+
Time $startTime
27+
) {
28+
$this->phaseIdentifier = $phaseIdentifier;
29+
$this->startTime = $startTime;
30+
}
31+
32+
public static function create(
33+
PhaseIdentifier $phaseIdentifier,
34+
Time $startTime
35+
): self {
36+
return new self(
37+
$phaseIdentifier,
38+
$startTime,
39+
);
40+
}
41+
42+
public function phaseIdentifier(): PhaseIdentifier
43+
{
44+
return $this->phaseIdentifier;
45+
}
46+
47+
public function startTime(): Time
48+
{
49+
return $this->startTime;
50+
}
51+
}

src/Subscriber/TestPassedSubscriber.php

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
use Ergebnis\PHPUnit\SlowTestDetector\Attribute;
1717
use Ergebnis\PHPUnit\SlowTestDetector\Collector;
1818
use Ergebnis\PHPUnit\SlowTestDetector\Duration;
19+
use Ergebnis\PHPUnit\SlowTestDetector\PhaseIdentifier;
1920
use Ergebnis\PHPUnit\SlowTestDetector\SlowTest;
2021
use Ergebnis\PHPUnit\SlowTestDetector\TestIdentifier;
2122
use Ergebnis\PHPUnit\SlowTestDetector\Time;
@@ -47,26 +48,28 @@ public function __construct(
4748
*/
4849
public function notify(Event\Test\Passed $event): void
4950
{
50-
$testIdentifier = TestIdentifier::fromString($event->test()->id());
51+
$phaseIdentifier = PhaseIdentifier::fromString($event->test()->id());
5152

5253
$time = $event->telemetryInfo()->time();
5354

54-
$duration = $this->timeKeeper->stop(
55-
$testIdentifier,
55+
$phase = $this->timeKeeper->stop(
56+
$phaseIdentifier,
5657
Time::fromSecondsAndNanoseconds(
5758
$time->seconds(),
5859
$time->nanoseconds(),
5960
),
6061
);
6162

63+
$duration = $phase->duration();
64+
6265
$maximumDuration = $this->resolveMaximumDuration($event->test());
6366

6467
if (!$duration->isGreaterThan($maximumDuration)) {
6568
return;
6669
}
6770

6871
$slowTest = SlowTest::create(
69-
$testIdentifier,
72+
TestIdentifier::fromString($event->test()->id()),
7073
$duration,
7174
$maximumDuration,
7275
);

src/Subscriber/TestPreparedSubscriber.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
namespace Ergebnis\PHPUnit\SlowTestDetector\Subscriber;
1515

16-
use Ergebnis\PHPUnit\SlowTestDetector\TestIdentifier;
16+
use Ergebnis\PHPUnit\SlowTestDetector\PhaseIdentifier;
1717
use Ergebnis\PHPUnit\SlowTestDetector\Time;
1818
use Ergebnis\PHPUnit\SlowTestDetector\TimeKeeper;
1919
use PHPUnit\Event;
@@ -38,7 +38,7 @@ public function notify(Event\Test\Prepared $event): void
3838
$time = $event->telemetryInfo()->time();
3939

4040
$this->timeKeeper->start(
41-
TestIdentifier::fromString($event->test()->id()),
41+
PhaseIdentifier::fromString($event->test()->id()),
4242
Time::fromSecondsAndNanoseconds(
4343
$time->seconds(),
4444
$time->nanoseconds(),

src/TimeKeeper.php

Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -19,36 +19,44 @@
1919
final class TimeKeeper
2020
{
2121
/**
22-
* @var array<string, Time>
22+
* @var array<string, PhaseStart>
2323
*/
24-
private array $startedTimes = [];
24+
private array $phaseStarts = [];
2525

2626
public function start(
27-
TestIdentifier $testIdentifier,
28-
Time $startedTime
27+
PhaseIdentifier $phaseIdentifier,
28+
Time $startTime
2929
): void {
30-
$key = $testIdentifier->toString();
30+
$key = $phaseIdentifier->toString();
3131

32-
$this->startedTimes[$key] = $startedTime;
32+
$this->phaseStarts[$key] = PhaseStart::create(
33+
$phaseIdentifier,
34+
$startTime,
35+
);
3336
}
3437

3538
public function stop(
36-
TestIdentifier $testIdentifier,
37-
Time $stoppedTime
38-
): Duration {
39-
$key = $testIdentifier->toString();
40-
41-
if (!\array_key_exists($key, $this->startedTimes)) {
42-
return Duration::fromSecondsAndNanoseconds(
43-
0,
44-
0,
39+
PhaseIdentifier $phaseIdentifier,
40+
Time $stopTime
41+
): Phase {
42+
$key = $phaseIdentifier->toString();
43+
44+
if (!\array_key_exists($key, $this->phaseStarts)) {
45+
return Phase::create(
46+
$phaseIdentifier,
47+
$stopTime,
48+
$stopTime,
4549
);
4650
}
4751

48-
$startedTime = $this->startedTimes[$key];
52+
$phaseStart = $this->phaseStarts[$key];
4953

50-
unset($this->startedTimes[$key]);
54+
unset($this->phaseStarts[$key]);
5155

52-
return $stoppedTime->duration($startedTime);
56+
return Phase::create(
57+
$phaseIdentifier,
58+
$phaseStart->startTime(),
59+
$stopTime,
60+
);
5361
}
5462
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/**
6+
* Copyright (c) 2021-2023 Andreas Möller
7+
*
8+
* For the full copyright and license information, please view
9+
* the LICENSE.md file that was distributed with this source code.
10+
*
11+
* @see https://github.com/ergebnis/phpunit-slow-test-detector
12+
*/
13+
14+
namespace Ergebnis\PHPUnit\SlowTestDetector\Test\Unit\Exception;
15+
16+
use Ergebnis\PHPUnit\SlowTestDetector\Exception;
17+
use Ergebnis\PHPUnit\SlowTestDetector\Test;
18+
use PHPUnit\Framework;
19+
20+
/**
21+
* @covers \Ergebnis\PHPUnit\SlowTestDetector\Exception\InvalidPhaseIdentifier
22+
*/
23+
final class InvalidPhaseIdentifierTest extends Framework\TestCase
24+
{
25+
use Test\Util\Helper;
26+
27+
public function testBlankOrEmptyReturnsException(): void
28+
{
29+
$exception = Exception\InvalidTestIdentifier::blankOrEmpty();
30+
31+
self::assertSame('Value can not be blank or empty.', $exception->getMessage());
32+
}
33+
}

0 commit comments

Comments
 (0)