Skip to content

Commit

Permalink
Merge pull request #222 from ergebnis/feature/maximum-duration
Browse files Browse the repository at this point in the history
Enhancement: Allow configuring the maximum duration via `@maximumDuration` annotation
  • Loading branch information
localheinz authored Feb 11, 2023
2 parents 097d98c + 4454d5e commit dbf50a2
Show file tree
Hide file tree
Showing 6 changed files with 125 additions and 27 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ For a full diff see [`1.0.0...main`][1.0.0...main].
- Allowed configuring the maximum count via `maximum-count` parameter ([#217]), by [@localheinz]
- Marked classes and interfaces as internal ([#219]), by [@localheinz]
- Brought duration formatting in line with `phpunit/php-timer` ([#220]), by [@localheinz]
- Allowed configuring the maximum duration via `@maximumDuration` annotation ([#222]), by [@localheinz]

### Fixed

Expand Down Expand Up @@ -89,5 +90,6 @@ For a full diff see [`7afa59c...1.0.0`][7afa59c...1.0.0].
[#219]: https://github.com/ergebnis/phpunit-slow-test-detector/pull/219
[#220]: https://github.com/ergebnis/phpunit-slow-test-detector/pull/220
[#221]: https://github.com/ergebnis/phpunit-slow-test-detector/pull/221
[#222]: https://github.com/ergebnis/phpunit-slow-test-detector/pull/222

[@localheinz]: https://github.com/localheinz
12 changes: 10 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ The following example configures the maximum count of slow tests to three, and t

#### Configuring the maximum duration per test case

You can configure the maximum duration for a single test with a `@slowThreshold` annotation in the DocBlock.
You can configure the maximum duration for a single test with a `@maximumDuration` (or `@slowThreshold`) annotation in the DocBlock.

The following example configures the maximum duration for a single test to 5.000 ms:

Expand All @@ -90,12 +90,20 @@ use PHPUnit\Framework;
final class ExtraSlowTest extends Framework\TestCase
{
/**
* @slowThreshold 5000
* @maximumDuration 5000
*/
public function testExtraExtraSlow(): void
{
// ...
}

/**
* @slowThreshold 4000
*/
public function testAlsoQuiteSlow(): void
{
// ...
}
}
```

Expand Down
4 changes: 2 additions & 2 deletions psalm-baseline.xml
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@
<code>symbolAnnotations</code>
</InternalMethod>
<MixedArgument>
<code>$slowThreshold</code>
<code>$maximumDuration</code>
</MixedArgument>
<MixedAssignment>
<code>$slowThreshold</code>
<code>$maximumDuration</code>
</MixedAssignment>
</file>
<file src="test/Double/Collector/AppendingCollector.php">
Expand Down
31 changes: 20 additions & 11 deletions src/Subscriber/TestPassedSubscriber.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,28 +56,37 @@ public function notify(Event\Test\Passed $event): void

private function resolveMaximumDuration(Event\Code\Test $test): Event\Telemetry\Duration
{
$annotations = [
'maximumDuration',
'slowThreshold',
];

/** @var Event\Code\TestMethod $test */
$docBlock = Metadata\Annotation\Parser\Registry::getInstance()->forMethod(
$test->className(),
$test->methodName(),
);

$annotations = $docBlock->symbolAnnotations();
$symbolAnnotations = $docBlock->symbolAnnotations();

if (!\array_key_exists('slowThreshold', $annotations)) {
return $this->maximumDuration->toTelemetryDuration();
}
foreach ($annotations as $annotation) {
if (!\array_key_exists($annotation, $symbolAnnotations)) {
continue;
}

if (!\is_array($annotations['slowThreshold'])) {
return $this->maximumDuration->toTelemetryDuration();
}
if (!\is_array($symbolAnnotations[$annotation])) {
continue;
}

$maximumDuration = \reset($symbolAnnotations[$annotation]);

$slowThreshold = \reset($annotations['slowThreshold']);
if (1 !== \preg_match('/^\d+$/', $maximumDuration)) {
continue;
}

if (1 !== \preg_match('/^\d+$/', $slowThreshold)) {
return $this->maximumDuration->toTelemetryDuration();
return MaximumDuration::fromMilliseconds((int) $maximumDuration)->toTelemetryDuration();
}

return MaximumDuration::fromMilliseconds((int) $slowThreshold)->toTelemetryDuration();
return $this->maximumDuration->toTelemetryDuration();
}
}
90 changes: 83 additions & 7 deletions test/EndToEnd/MaximumDuration/Fifty/SleeperTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public function testSleeperDoesNotSleepAtAll(): void

public function testSleeperSleepsJustBelowMaximumDuration(): void
{
$milliseconds = 40;
$milliseconds = 30;

$sleeper = Test\Fixture\Sleeper::fromMilliseconds($milliseconds);

Expand All @@ -49,7 +49,7 @@ public function testSleeperSleepsJustBelowMaximumDuration(): void

public function testSleeperSleepsJustAboveDefaultMaximumDuration(): void
{
$milliseconds = 60;
$milliseconds = 70;

$sleeper = Test\Fixture\Sleeper::fromMilliseconds($milliseconds);

Expand All @@ -63,7 +63,49 @@ public function testSleeperSleepsJustAboveDefaultMaximumDuration(): void
*/
public function testSleeperSleepsWithDocBlockWithoutSlowThresholdAnnotation(): void
{
$milliseconds = 80;
$milliseconds = 90;

$sleeper = Test\Fixture\Sleeper::fromMilliseconds($milliseconds);

$sleeper->sleep();

self::assertSame($milliseconds, $sleeper->milliseconds());
}

/**
* @maximumDuration 3.14
*/
public function testSleeperSleepsWithDocBlockWithMaximumDurationAnnotationWhereValueIsNotAnInt(): void
{
$milliseconds = 110;

$sleeper = Test\Fixture\Sleeper::fromMilliseconds($milliseconds);

$sleeper->sleep();

self::assertSame($milliseconds, $sleeper->milliseconds());
}

/**
* @maximumDuration 140
*/
public function testSleeperSleepsShorterThanMaximumDurationFromMaximumDurationAnnotation(): void
{
$milliseconds = 130;

$sleeper = Test\Fixture\Sleeper::fromMilliseconds($milliseconds);

$sleeper->sleep();

self::assertSame($milliseconds, $sleeper->milliseconds());
}

/**
* @maximumDuration 150
*/
public function testSleeperSleepsLongerThanMaximumDurationFromMaximumDurationAnnotation(): void
{
$milliseconds = 150;

$sleeper = Test\Fixture\Sleeper::fromMilliseconds($milliseconds);

Expand All @@ -73,11 +115,45 @@ public function testSleeperSleepsWithDocBlockWithoutSlowThresholdAnnotation(): v
}

/**
* @maximumDuration 160
*
* @slowThreshold 120
*/
public function testSleeperSleepsLongerThanMaximumDurationFromMaximumDurationAnnotationWhenSlowThresholdAnnotationIsPresentAfterMaximumDuration(): void
{
$milliseconds = 170;

$sleeper = Test\Fixture\Sleeper::fromMilliseconds($milliseconds);

$sleeper->sleep();

self::assertSame($milliseconds, $sleeper->milliseconds());
}

/**
* @slowThreshold 120
*
* @maximumDuration 180
*/
public function testSleeperSleepsLongerThanMaximumDurationFromMaximumDurationAnnotationWhenSlowThresholdAnnotationIsPresentBeforeMaximumDuration(): void
{
$milliseconds = 200;

$sleeper = Test\Fixture\Sleeper::fromMilliseconds($milliseconds);

$sleeper->sleep();

self::assertSame($milliseconds, $sleeper->milliseconds());
}

/**
* @see https://github.com/johnkary/phpunit-speedtrap/blob/1.0/src/JohnKary/PHPUnit/Listener/SpeedTrapListener.php#L309-L331
*
* @slowThreshold 3.14
*/
public function testSleeperSleepsWithDocBlockWithSlowThresholdAnnotationWhereValueIsNotAnInt(): void
{
$milliseconds = 100;
$milliseconds = 40;

$sleeper = Test\Fixture\Sleeper::fromMilliseconds($milliseconds);

Expand All @@ -93,7 +169,7 @@ public function testSleeperSleepsWithDocBlockWithSlowThresholdAnnotationWhereVal
*/
public function testSleeperSleepsShorterThanMaximumDurationFromSlowThresholdAnnotation(): void
{
$milliseconds = 90;
$milliseconds = 80;

$sleeper = Test\Fixture\Sleeper::fromMilliseconds($milliseconds);

Expand All @@ -105,11 +181,11 @@ public function testSleeperSleepsShorterThanMaximumDurationFromSlowThresholdAnno
/**
* @see https://github.com/johnkary/phpunit-speedtrap/blob/1.0/src/JohnKary/PHPUnit/Listener/SpeedTrapListener.php#L309-L331
*
* @slowThreshold 100
* @slowThreshold 200
*/
public function testSleeperSleepsLongerThanMaximumDurationFromSlowThresholdAnnotation(): void
{
$milliseconds = 120;
$milliseconds = 220;

$sleeper = Test\Fixture\Sleeper::fromMilliseconds($milliseconds);

Expand Down
13 changes: 8 additions & 5 deletions test/EndToEnd/MaximumDuration/Fifty/test.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,18 @@ Runtime: %s
Configuration: test/EndToEnd/MaximumDuration/Fifty/phpunit.xml
Random Seed: %s

....... 7 / 7 (100%)
............ 12 / 12 (100%)

Detected 4 tests that took longer than expected.
Detected 7 tests that took longer than expected.

0.1%s (0.100) Ergebnis\PHPUnit\SlowTestDetector\Test\EndToEnd\MaximumDuration\Fifty\SleeperTest::testSleeperSleepsLongerThanMaximumDurationFromSlowThresholdAnnotation
0.1%s (0.050) Ergebnis\PHPUnit\SlowTestDetector\Test\EndToEnd\MaximumDuration\Fifty\SleeperTest::testSleeperSleepsWithDocBlockWithSlowThresholdAnnotationWhereValueIsNotAnInt
0.2%s (0.200) Ergebnis\PHPUnit\SlowTestDetector\Test\EndToEnd\MaximumDuration\Fifty\SleeperTest::testSleeperSleepsLongerThanMaximumDurationFromSlowThresholdAnnotation
0.2%s (0.180) Ergebnis\PHPUnit\SlowTestDetector\Test\EndToEnd\MaximumDuration\Fifty\SleeperTest::testSleeperSleepsLongerThanMaximumDurationFromMaximumDurationAnnotationWhenSlowThresholdAnnotationIsPresentBeforeMaximumDuration
0.1%s (0.160) Ergebnis\PHPUnit\SlowTestDetector\Test\EndToEnd\MaximumDuration\Fifty\SleeperTest::testSleeperSleepsLongerThanMaximumDurationFromMaximumDurationAnnotationWhenSlowThresholdAnnotationIsPresentAfterMaximumDuration
0.1%s (0.150) Ergebnis\PHPUnit\SlowTestDetector\Test\EndToEnd\MaximumDuration\Fifty\SleeperTest::testSleeperSleepsLongerThanMaximumDurationFromMaximumDurationAnnotation
0.1%s (0.050) Ergebnis\PHPUnit\SlowTestDetector\Test\EndToEnd\MaximumDuration\Fifty\SleeperTest::testSleeperSleepsWithDocBlockWithMaximumDurationAnnotationWhereValueIsNotAnInt
0.0%s (0.050) Ergebnis\PHPUnit\SlowTestDetector\Test\EndToEnd\MaximumDuration\Fifty\SleeperTest::testSleeperSleepsWithDocBlockWithoutSlowThresholdAnnotation
0.0%s (0.050) Ergebnis\PHPUnit\SlowTestDetector\Test\EndToEnd\MaximumDuration\Fifty\SleeperTest::testSleeperSleepsJustAboveDefaultMaximumDuration

Time: %s, Memory: %s

OK (7 tests, 7 assertions)
OK (12 tests, 12 assertions)

0 comments on commit dbf50a2

Please sign in to comment.