From 4454d5e65a3d3f88068d1780b7b9111c2272a2ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20M=C3=B6ller?= Date: Sat, 11 Feb 2023 09:48:54 +0100 Subject: [PATCH] Enhancement: Allow configuring the maximum duration via maximumDuration annotation --- CHANGELOG.md | 2 + README.md | 12 ++- psalm-baseline.xml | 4 +- src/Subscriber/TestPassedSubscriber.php | 31 ++++--- .../MaximumDuration/Fifty/SleeperTest.php | 90 +++++++++++++++++-- test/EndToEnd/MaximumDuration/Fifty/test.phpt | 13 +-- 6 files changed, 125 insertions(+), 27 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 769f6171..bc98e9fd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 @@ -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 diff --git a/README.md b/README.md index a66f4e3a..356700b8 100644 --- a/README.md +++ b/README.md @@ -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: @@ -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 + { + // ... + } } ``` diff --git a/psalm-baseline.xml b/psalm-baseline.xml index 76a5b48e..79bfeae1 100644 --- a/psalm-baseline.xml +++ b/psalm-baseline.xml @@ -25,10 +25,10 @@ symbolAnnotations - $slowThreshold + $maximumDuration - $slowThreshold + $maximumDuration diff --git a/src/Subscriber/TestPassedSubscriber.php b/src/Subscriber/TestPassedSubscriber.php index 5a479395..cbe923c1 100644 --- a/src/Subscriber/TestPassedSubscriber.php +++ b/src/Subscriber/TestPassedSubscriber.php @@ -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(); } } diff --git a/test/EndToEnd/MaximumDuration/Fifty/SleeperTest.php b/test/EndToEnd/MaximumDuration/Fifty/SleeperTest.php index 9bcb091d..ace46b34 100644 --- a/test/EndToEnd/MaximumDuration/Fifty/SleeperTest.php +++ b/test/EndToEnd/MaximumDuration/Fifty/SleeperTest.php @@ -38,7 +38,7 @@ public function testSleeperDoesNotSleepAtAll(): void public function testSleeperSleepsJustBelowMaximumDuration(): void { - $milliseconds = 40; + $milliseconds = 30; $sleeper = Test\Fixture\Sleeper::fromMilliseconds($milliseconds); @@ -49,7 +49,7 @@ public function testSleeperSleepsJustBelowMaximumDuration(): void public function testSleeperSleepsJustAboveDefaultMaximumDuration(): void { - $milliseconds = 60; + $milliseconds = 70; $sleeper = Test\Fixture\Sleeper::fromMilliseconds($milliseconds); @@ -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); @@ -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); @@ -93,7 +169,7 @@ public function testSleeperSleepsWithDocBlockWithSlowThresholdAnnotationWhereVal */ public function testSleeperSleepsShorterThanMaximumDurationFromSlowThresholdAnnotation(): void { - $milliseconds = 90; + $milliseconds = 80; $sleeper = Test\Fixture\Sleeper::fromMilliseconds($milliseconds); @@ -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); diff --git a/test/EndToEnd/MaximumDuration/Fifty/test.phpt b/test/EndToEnd/MaximumDuration/Fifty/test.phpt index 967b41c6..f67f3e74 100644 --- a/test/EndToEnd/MaximumDuration/Fifty/test.phpt +++ b/test/EndToEnd/MaximumDuration/Fifty/test.phpt @@ -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)