diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 220fd9eb..2a714a87 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -110,6 +110,16 @@ parameters: count: 1 path: test/Unit/Console/ColorTest.php + - + message: "#^Method Ergebnis\\\\PHPUnit\\\\SlowTestDetector\\\\Test\\\\Unit\\\\CountTest\\:\\:testEqualsReturnsFalseWhenValueIsDifferent\\(\\) has no return type specified\\.$#" + count: 1 + path: test/Unit/CountTest.php + + - + message: "#^Method Ergebnis\\\\PHPUnit\\\\SlowTestDetector\\\\Test\\\\Unit\\\\CountTest\\:\\:testEqualsReturnsTrueWhenValueIsSame\\(\\) has no return type specified\\.$#" + count: 1 + path: test/Unit/CountTest.php + - message: "#^Method Ergebnis\\\\PHPUnit\\\\SlowTestDetector\\\\Test\\\\Unit\\\\CountTest\\:\\:testFromIntRejectsInvalidValue\\(\\) has no return type specified\\.$#" count: 1 @@ -265,6 +275,11 @@ parameters: count: 1 path: test/Unit/Exception/PhaseNotStartedTest.php + - + message: "#^Method Ergebnis\\\\PHPUnit\\\\SlowTestDetector\\\\Test\\\\Unit\\\\Exception\\\\SlowTestListIsEmptyTest\\:\\:testFromPhaseIdentifierReturnsException\\(\\) has no return type specified\\.$#" + count: 1 + path: test/Unit/Exception/SlowTestListIsEmptyTest.php + - message: "#^Method Ergebnis\\\\PHPUnit\\\\SlowTestDetector\\\\Test\\\\Unit\\\\Formatter\\\\DefaultDurationFormatterTest\\:\\:testFormatFormats\\(\\) has no return type specified\\.$#" count: 1 @@ -316,15 +331,80 @@ parameters: path: test/Unit/PhaseTest.php - - message: "#^Method Ergebnis\\\\PHPUnit\\\\SlowTestDetector\\\\Test\\\\Unit\\\\Reporter\\\\DefaultReporterTest\\:\\:testReportReturnsEmptyStringWhenThereAreNoSlowTests\\(\\) has no return type specified\\.$#" + message: "#^Method Ergebnis\\\\PHPUnit\\\\SlowTestDetector\\\\Test\\\\Unit\\\\Reporter\\\\DefaultReporterTest\\:\\:testReportReturnsEmptyStringWhenSlowTestListIsEmpty\\(\\) has no return type specified\\.$#" count: 1 path: test/Unit/Reporter/DefaultReporterTest.php - - message: "#^Method Ergebnis\\\\PHPUnit\\\\SlowTestDetector\\\\Test\\\\Unit\\\\Reporter\\\\DefaultReporterTest\\:\\:testReportReturnsReportWhenThereAreFewerSlowTestsThanMaximumCount\\(\\) has no return type specified\\.$#" + message: "#^Method Ergebnis\\\\PHPUnit\\\\SlowTestDetector\\\\Test\\\\Unit\\\\Reporter\\\\DefaultReporterTest\\:\\:testReportReturnsReportWhenSlowTestListHasFewerSlowTestsThanMaximumCount\\(\\) has no return type specified\\.$#" count: 1 path: test/Unit/Reporter/DefaultReporterTest.php + - + message: "#^Method SlowTestCountTest\\:\\:testEqualsReturnsFalseWhenValueIsDifferent\\(\\) has no return type specified\\.$#" + count: 1 + path: test/Unit/SlowTestCountTest.php + + - + message: "#^Method SlowTestCountTest\\:\\:testEqualsReturnsFalseWhenValueIsSame\\(\\) has no return type specified\\.$#" + count: 1 + path: test/Unit/SlowTestCountTest.php + + - + message: "#^Method SlowTestCountTest\\:\\:testFromCountReturnsMaximumCount\\(\\) has no return type specified\\.$#" + count: 1 + path: test/Unit/SlowTestCountTest.php + + - + message: "#^Method Ergebnis\\\\PHPUnit\\\\SlowTestDetector\\\\Test\\\\Unit\\\\SlowTestListTest\\:\\:testCreateReturnsSlowTestList\\(\\) has no return type specified\\.$#" + count: 1 + path: test/Unit/SlowTestListTest.php + + - + message: "#^Method Ergebnis\\\\PHPUnit\\\\SlowTestDetector\\\\Test\\\\Unit\\\\SlowTestListTest\\:\\:testFirstReturnsFirstSlowTestWhenSlowTestListIsNotEmpty\\(\\) has no return type specified\\.$#" + count: 1 + path: test/Unit/SlowTestListTest.php + + - + message: "#^Method Ergebnis\\\\PHPUnit\\\\SlowTestDetector\\\\Test\\\\Unit\\\\SlowTestListTest\\:\\:testFirstThrowsExceptionWhenSlowTestListIsEmpty\\(\\) has no return type specified\\.$#" + count: 1 + path: test/Unit/SlowTestListTest.php + + - + message: "#^Method Ergebnis\\\\PHPUnit\\\\SlowTestDetector\\\\Test\\\\Unit\\\\SlowTestListTest\\:\\:testIsEmptyReturnsFalseWhenSlowTestListIsNotEmpty\\(\\) has no return type specified\\.$#" + count: 1 + path: test/Unit/SlowTestListTest.php + + - + message: "#^Method Ergebnis\\\\PHPUnit\\\\SlowTestDetector\\\\Test\\\\Unit\\\\SlowTestListTest\\:\\:testIsEmptyReturnsTrueWhenSlowTestListIsEmpty\\(\\) has no return type specified\\.$#" + count: 1 + path: test/Unit/SlowTestListTest.php + + - + message: "#^Method Ergebnis\\\\PHPUnit\\\\SlowTestDetector\\\\Test\\\\Unit\\\\SlowTestListTest\\:\\:testLimitReturnsSlowTestListWhenSlowTestListHasFewerSlowTests\\(\\) has no return type specified\\.$#" + count: 1 + path: test/Unit/SlowTestListTest.php + + - + message: "#^Method Ergebnis\\\\PHPUnit\\\\SlowTestDetector\\\\Test\\\\Unit\\\\SlowTestListTest\\:\\:testLimitReturnsSlowTestListWhenSlowTestListHasMoreSlowTests\\(\\) has no return type specified\\.$#" + count: 1 + path: test/Unit/SlowTestListTest.php + + - + message: "#^Method Ergebnis\\\\PHPUnit\\\\SlowTestDetector\\\\Test\\\\Unit\\\\SlowTestListTest\\:\\:testSlowTestCountReturnsCountOfSlowTests\\(\\) has no return type specified\\.$#" + count: 1 + path: test/Unit/SlowTestListTest.php + + - + message: "#^Method Ergebnis\\\\PHPUnit\\\\SlowTestDetector\\\\Test\\\\Unit\\\\SlowTestListTest\\:\\:testSortByMaximumDurationDescendingReturnsSlowTestListWhereSlowTestsAreSortedByMaximumDurationDescending\\(\\) has no return type specified\\.$#" + count: 1 + path: test/Unit/SlowTestListTest.php + + - + message: "#^Method Ergebnis\\\\PHPUnit\\\\SlowTestDetector\\\\Test\\\\Unit\\\\SlowTestListTest\\:\\:testSortByTestDurationDescendingReturnsSlowTestListWhereSlowTestsAreSortedByTestDurationDescending\\(\\) has no return type specified\\.$#" + count: 1 + path: test/Unit/SlowTestListTest.php + - message: "#^Method Ergebnis\\\\PHPUnit\\\\SlowTestDetector\\\\Test\\\\Unit\\\\SlowTestTest\\:\\:testCreateReturnsSlowTest\\(\\) has no return type specified\\.$#" count: 1 diff --git a/src/Collector/Collector.php b/src/Collector/Collector.php index 8dfeac19..f65b4cb1 100644 --- a/src/Collector/Collector.php +++ b/src/Collector/Collector.php @@ -14,6 +14,7 @@ namespace Ergebnis\PHPUnit\SlowTestDetector\Collector; use Ergebnis\PHPUnit\SlowTestDetector\SlowTest; +use Ergebnis\PHPUnit\SlowTestDetector\SlowTestList; /** * @internal @@ -22,10 +23,5 @@ interface Collector { public function collectSlowTest(SlowTest $slowTest); - /** - * @phpstan-return list - * - * @return list - */ - public function collected(): array; + public function slowTestList(): SlowTestList; } diff --git a/src/Collector/DefaultCollector.php b/src/Collector/DefaultCollector.php index 77e8ceee..e78f00e6 100644 --- a/src/Collector/DefaultCollector.php +++ b/src/Collector/DefaultCollector.php @@ -14,6 +14,7 @@ namespace Ergebnis\PHPUnit\SlowTestDetector\Collector; use Ergebnis\PHPUnit\SlowTestDetector\SlowTest; +use Ergebnis\PHPUnit\SlowTestDetector\SlowTestList; /** * @internal @@ -44,13 +45,8 @@ public function collectSlowTest(SlowTest $slowTest) $this->slowTests[$key] = $slowTest; } - /** - * @phpstan-return list - * - * @return list - */ - public function collected(): array + public function slowTestList(): SlowTestList { - return \array_values($this->slowTests); + return SlowTestList::create(...\array_values($this->slowTests)); } } diff --git a/src/Count.php b/src/Count.php index 084e1eaa..613907a1 100644 --- a/src/Count.php +++ b/src/Count.php @@ -40,6 +40,11 @@ public static function fromInt(int $value): self return new self($value); } + public function equals(self $other): bool + { + return $this->value === $other->value; + } + public function toInt(): int { return $this->value; diff --git a/src/Exception/SlowTestListIsEmpty.php b/src/Exception/SlowTestListIsEmpty.php new file mode 100644 index 00000000..d6d96dd9 --- /dev/null +++ b/src/Exception/SlowTestListIsEmpty.php @@ -0,0 +1,25 @@ +collector = new Collector\DefaultCollector(); $this->reporter = new Reporter\DefaultReporter( new Formatter\DefaultDurationFormatter(), - $maximumDuration, $maximumCount ); } @@ -129,13 +128,13 @@ public function endTestSuite(Framework\TestSuite $suite) return; } - $slowTests = $this->collector->collected(); + $slowTestList = $this->collector->slowTestList(); - if ([] === $slowTests) { + if ($slowTestList->isEmpty()) { return; } - $report = $this->reporter->report(...$slowTests); + $report = $this->reporter->report($slowTestList); if ('' === $report) { return; @@ -277,7 +276,6 @@ public function __construct(array $options = []) $this->collector = new Collector\DefaultCollector(); $this->reporter = new Reporter\DefaultReporter( new Formatter\DefaultDurationFormatter(), - $maximumDuration, $maximumCount ); } @@ -335,13 +333,13 @@ public function executeAfterLastTest(): void return; } - $slowTests = $this->collector->collected(); + $slowTestList = $this->collector->slowTestList(); - if ([] === $slowTests) { + if ($slowTestList->isEmpty()) { return; } - $report = $this->reporter->report(...$slowTests); + $report = $this->reporter->report($slowTestList); if ('' === $report) { return; @@ -431,7 +429,6 @@ public function bootstrap( $collector = new Collector\DefaultCollector(); $reporter = new Reporter\DefaultReporter( new Formatter\DefaultDurationFormatter(), - $maximumDuration, $maximumCount ); diff --git a/src/Reporter/DefaultReporter.php b/src/Reporter/DefaultReporter.php index abfb0472..835f434b 100644 --- a/src/Reporter/DefaultReporter.php +++ b/src/Reporter/DefaultReporter.php @@ -13,11 +13,12 @@ namespace Ergebnis\PHPUnit\SlowTestDetector\Reporter; -use Ergebnis\PHPUnit\SlowTestDetector\Comparator; +use Ergebnis\PHPUnit\SlowTestDetector\Count; use Ergebnis\PHPUnit\SlowTestDetector\Formatter; use Ergebnis\PHPUnit\SlowTestDetector\MaximumCount; -use Ergebnis\PHPUnit\SlowTestDetector\MaximumDuration; use Ergebnis\PHPUnit\SlowTestDetector\SlowTest; +use Ergebnis\PHPUnit\SlowTestDetector\SlowTestCount; +use Ergebnis\PHPUnit\SlowTestDetector\SlowTestList; /** * @internal @@ -29,41 +30,28 @@ final class DefaultReporter implements Reporter */ private $durationFormatter; - /** - * @var MaximumDuration - */ - private $maximumDuration; - /** * @var MaximumCount */ private $maximumCount; - /** - * @var Comparator\DurationComparator - */ - private $durationComparator; - public function __construct( Formatter\DurationFormatter $durationFormatter, - MaximumDuration $maximumDuration, MaximumCount $maximumCount ) { $this->durationFormatter = $durationFormatter; - $this->maximumDuration = $maximumDuration; $this->maximumCount = $maximumCount; - $this->durationComparator = new Comparator\DurationComparator(); } - public function report(SlowTest ...$slowTests): string + public function report(SlowTestList $slowTestList): string { - if ([] === $slowTests) { + if ($slowTestList->isEmpty()) { return ''; } - $header = $this->header(...$slowTests); - $list = $this->list(...$slowTests); - $footer = $this->footer(...$slowTests); + $header = $this->header($slowTestList); + $list = $this->list($slowTestList); + $footer = $this->footer($slowTestList); if ('' === $footer) { return <<slowTestCount(); - if (1 === $count) { - return <<toCount()->equals(Count::fromInt(1))) { + return <<<'TXT' +Detected 1 test where the duration exceeded the maximum duration. TXT; } - return <<toCount()->toInt() + ); } - private function list(SlowTest ...$slowTests): string + private function list(SlowTestList $slowTestList): string { - $durationComparator = $this->durationComparator; + $slowTestListThatWillBeReported = $slowTestList + ->sortByTestDurationDescending() + ->limit($this->maximumCount); - \usort($slowTests, static function (SlowTest $one, SlowTest $two) use ($durationComparator): int { - return $durationComparator->compare( - $two->testDuration()->toDuration(), - $one->testDuration()->toDuration() - ); - }); + $slowTestWithLongestTestDuration = $slowTestListThatWillBeReported->first(); - $slowTestsToReport = \array_slice( - $slowTests, - 0, - $this->maximumCount->toCount()->toInt() - ); - - /** @var SlowTest $slowTestWithLongestTestDuration */ - $slowTestWithLongestTestDuration = \reset($slowTestsToReport); - - $longestMaximumDuration = \array_reduce( - $slowTestsToReport, - static function (MaximumDuration $maximumDuration, SlowTest $slowTest): MaximumDuration { - if ($maximumDuration->toDuration()->isLessThan($slowTest->maximumDuration()->toDuration())) { - return $slowTest->maximumDuration(); - } - - return $maximumDuration; - }, - $this->maximumDuration - ); + $slowTestWithLongestMaximumDuration = $slowTestListThatWillBeReported->sortByMaximumDurationDescending()->first(); $durationFormatter = $this->durationFormatter; - $numberWidth = \strlen((string) \count($slowTestsToReport)); + $numberWidth = \strlen((string) $slowTestListThatWillBeReported->slowTestCount()->toCount()->toInt()); $testDurationWidth = \strlen($durationFormatter->format($slowTestWithLongestTestDuration->testDuration()->toDuration())); - $maximumDurationWidth = \strlen($durationFormatter->format($longestMaximumDuration->toDuration())); + $maximumDurationWidth = \strlen($durationFormatter->format($slowTestWithLongestMaximumDuration->maximumDuration()->toDuration())); $items = \array_map(static function (int $number, SlowTest $slowTest) use ($numberWidth, $durationFormatter, $testDurationWidth, $maximumDurationWidth): string { $formattedNumber = \str_pad( @@ -164,7 +134,7 @@ static function (MaximumDuration $maximumDuration, SlowTest $slowTest): MaximumD return <<slowTestCount()->toCount()->toInt()), $slowTestListThatWillBeReported->toArray()); return \implode( "\n", @@ -172,27 +142,31 @@ static function (MaximumDuration $maximumDuration, SlowTest $slowTest): MaximumD ); } - private function footer(SlowTest ...$slowTests): string + private function footer(SlowTestList $slowTestList): string { - $additionalSlowTestCount = \max( - \count($slowTests) - $this->maximumCount->toCount()->toInt(), - 0 - ); + $additionalSlowTestCount = SlowTestCount::fromCount(Count::fromInt(\max( + 0, + $slowTestList->slowTestCount()->toCount()->toInt() - $this->maximumCount->toCount()->toInt() + ))); - if (0 === $additionalSlowTestCount) { + if ($additionalSlowTestCount->equals(SlowTestCount::fromCount(Count::fromInt(0)))) { return ''; } - if (1 === $additionalSlowTestCount) { + if ($additionalSlowTestCount->equals(SlowTestCount::fromCount(Count::fromInt(1)))) { return <<<'TXT' There is 1 additional slow test that is not listed here. TXT; } - return <<toCount()->toInt() + ); } } diff --git a/src/Reporter/Reporter.php b/src/Reporter/Reporter.php index e7fb491d..721be13e 100644 --- a/src/Reporter/Reporter.php +++ b/src/Reporter/Reporter.php @@ -13,12 +13,12 @@ namespace Ergebnis\PHPUnit\SlowTestDetector\Reporter; -use Ergebnis\PHPUnit\SlowTestDetector\SlowTest; +use Ergebnis\PHPUnit\SlowTestDetector\SlowTestList; /** * @internal */ interface Reporter { - public function report(SlowTest ...$slowTests): string; + public function report(SlowTestList $slowTestList): string; } diff --git a/src/SlowTestCount.php b/src/SlowTestCount.php new file mode 100644 index 00000000..5140381c --- /dev/null +++ b/src/SlowTestCount.php @@ -0,0 +1,42 @@ +count = $count; + } + + public static function fromCount(Count $count): self + { + return new self($count); + } + + public function toCount(): Count + { + return $this->count; + } + + public function equals(self $other): bool + { + return $this->count->equals($other->toCount()); + } +} diff --git a/src/SlowTestList.php b/src/SlowTestList.php new file mode 100644 index 00000000..e05cf223 --- /dev/null +++ b/src/SlowTestList.php @@ -0,0 +1,108 @@ + + */ + private $slowTests; + + private function __construct(SlowTest ...$slowTests) + { + $this->slowTests = $slowTests; + } + + public static function create(SlowTest ...$slowTests): self + { + return new self(...$slowTests); + } + + public function slowTestCount(): SlowTestCount + { + return SlowTestCount::fromCount(Count::fromInt(\count($this->slowTests))); + } + + /** + * @throws Exception\SlowTestListIsEmpty + */ + public function first(): SlowTest + { + if ([] === $this->slowTests) { + throw Exception\SlowTestListIsEmpty::create(); + } + + return \reset($this->slowTests); + } + + public function isEmpty(): bool + { + return [] === $this->slowTests; + } + + public function limit(MaximumCount $maximumCount): self + { + return self::create(...\array_slice( + $this->slowTests, + 0, + $maximumCount->toCount()->toInt() + )); + } + + public function sortByTestDurationDescending(): self + { + $durationComparator = new DurationComparator(); + + $slowTests = $this->slowTests; + + \usort($slowTests, static function (SlowTest $one, SlowTest $two) use ($durationComparator): int { + return $durationComparator->compare( + $two->testDuration()->toDuration(), + $one->testDuration()->toDuration() + ); + }); + + return self::create(...$slowTests); + } + + public function sortByMaximumDurationDescending(): self + { + $durationComparator = new DurationComparator(); + + $slowTests = $this->slowTests; + + \usort($slowTests, static function (SlowTest $one, SlowTest $two) use ($durationComparator): int { + return $durationComparator->compare( + $two->maximumDuration()->toDuration(), + $one->maximumDuration()->toDuration() + ); + }); + + return self::create(...$slowTests); + } + + /** + * @return list + */ + public function toArray(): array + { + return $this->slowTests; + } +} diff --git a/src/Subscriber/TestRunner/ExecutionFinishedSubscriber.php b/src/Subscriber/TestRunner/ExecutionFinishedSubscriber.php index e66155f0..6cf868e0 100644 --- a/src/Subscriber/TestRunner/ExecutionFinishedSubscriber.php +++ b/src/Subscriber/TestRunner/ExecutionFinishedSubscriber.php @@ -45,13 +45,13 @@ public function __construct( */ public function notify(Event\TestRunner\ExecutionFinished $event): void { - $slowTests = $this->collector->collected(); + $slowTestList = $this->collector->slowTestList(); - if ([] === $slowTests) { + if ($slowTestList->isEmpty()) { return; } - $report = $this->reporter->report(...$slowTests); + $report = $this->reporter->report($slowTestList); if ('' === $report) { return; diff --git a/test/Unit/Collector/DefaultCollectorTest.php b/test/Unit/Collector/DefaultCollectorTest.php index eaa496a4..ba1ba023 100644 --- a/test/Unit/Collector/DefaultCollectorTest.php +++ b/test/Unit/Collector/DefaultCollectorTest.php @@ -17,6 +17,7 @@ use Ergebnis\PHPUnit\SlowTestDetector\Duration; use Ergebnis\PHPUnit\SlowTestDetector\MaximumDuration; use Ergebnis\PHPUnit\SlowTestDetector\SlowTest; +use Ergebnis\PHPUnit\SlowTestDetector\SlowTestList; use Ergebnis\PHPUnit\SlowTestDetector\Test; use Ergebnis\PHPUnit\SlowTestDetector\TestDescription; use Ergebnis\PHPUnit\SlowTestDetector\TestDuration; @@ -29,6 +30,7 @@ * @uses \Ergebnis\PHPUnit\SlowTestDetector\Duration * @uses \Ergebnis\PHPUnit\SlowTestDetector\MaximumDuration * @uses \Ergebnis\PHPUnit\SlowTestDetector\SlowTest + * @uses \Ergebnis\PHPUnit\SlowTestDetector\SlowTestList * @uses \Ergebnis\PHPUnit\SlowTestDetector\TestDescription * @uses \Ergebnis\PHPUnit\SlowTestDetector\TestDuration * @uses \Ergebnis\PHPUnit\SlowTestDetector\TestIdentifier @@ -60,12 +62,12 @@ public function testCollectSlowTestCollectsSlowTests() $collector->collectSlowTest($one); $collector->collectSlowTest($two); - $expected = [ + $expected = SlowTestList::create( $one, - $two, - ]; + $two + ); - self::assertSame($expected, $collector->collected()); + self::assertEquals($expected, $collector->slowTestList()); } public function testCollectSlowTestCollectsSlowerTestWithSameTestIdentifier() @@ -94,11 +96,9 @@ public function testCollectSlowTestCollectsSlowerTestWithSameTestIdentifier() $collector->collectSlowTest($one); $collector->collectSlowTest($two); - $expected = [ - $two, - ]; + $expected = SlowTestList::create($two); - self::assertSame($expected, $collector->collected()); + self::assertEquals($expected, $collector->slowTestList()); } public function testCollectSlowTestDoesNotCollectFasterTestWithSameTestIdentifier() @@ -127,10 +127,8 @@ public function testCollectSlowTestDoesNotCollectFasterTestWithSameTestIdentifie $collector->collectSlowTest($one); $collector->collectSlowTest($two); - $expected = [ - $one, - ]; + $expected = SlowTestList::create($one); - self::assertSame($expected, $collector->collected()); + self::assertEquals($expected, $collector->slowTestList()); } } diff --git a/test/Unit/CountTest.php b/test/Unit/CountTest.php index 8a8d124b..7c661450 100644 --- a/test/Unit/CountTest.php +++ b/test/Unit/CountTest.php @@ -15,6 +15,7 @@ use Ergebnis\PHPUnit\SlowTestDetector\Count; use Ergebnis\PHPUnit\SlowTestDetector\Exception; +use Ergebnis\PHPUnit\SlowTestDetector\Test; use PHPUnit\Framework; /** @@ -24,6 +25,8 @@ */ final class CountTest extends Framework\TestCase { + use Test\Util\Helper; + /** * @dataProvider \Ergebnis\PHPUnit\SlowTestDetector\Test\DataProvider\IntProvider::lessThanZero */ @@ -44,4 +47,24 @@ public function testFromIntReturnsCount(int $value) self::assertSame($value, $count->toInt()); } + + public function testEqualsReturnsFalseWhenValueIsDifferent() + { + $faker = self::faker()->unique(); + + $one = Count::fromInt($faker->numberBetween(0)); + $two = Count::fromInt($faker->numberBetween(0)); + + self::assertFalse($one->equals($two)); + } + + public function testEqualsReturnsTrueWhenValueIsSame() + { + $value = self::faker()->numberBetween(0); + + $one = Count::fromInt($value); + $two = Count::fromInt($value); + + self::assertTrue($one->equals($two)); + } } diff --git a/test/Unit/Exception/SlowTestListIsEmptyTest.php b/test/Unit/Exception/SlowTestListIsEmptyTest.php new file mode 100644 index 00000000..9e046f7f --- /dev/null +++ b/test/Unit/Exception/SlowTestListIsEmptyTest.php @@ -0,0 +1,32 @@ +getMessage()); + } +} diff --git a/test/Unit/Reporter/DefaultReporterTest.php b/test/Unit/Reporter/DefaultReporterTest.php index 328b722f..25ee2f79 100644 --- a/test/Unit/Reporter/DefaultReporterTest.php +++ b/test/Unit/Reporter/DefaultReporterTest.php @@ -20,6 +20,7 @@ use Ergebnis\PHPUnit\SlowTestDetector\MaximumDuration; use Ergebnis\PHPUnit\SlowTestDetector\Reporter; use Ergebnis\PHPUnit\SlowTestDetector\SlowTest; +use Ergebnis\PHPUnit\SlowTestDetector\SlowTestList; use Ergebnis\PHPUnit\SlowTestDetector\Test; use Ergebnis\PHPUnit\SlowTestDetector\TestDescription; use Ergebnis\PHPUnit\SlowTestDetector\TestDuration; @@ -33,8 +34,11 @@ * @uses \Ergebnis\PHPUnit\SlowTestDetector\Count * @uses \Ergebnis\PHPUnit\SlowTestDetector\Duration * @uses \Ergebnis\PHPUnit\SlowTestDetector\Formatter\DefaultDurationFormatter + * @uses \Ergebnis\PHPUnit\SlowTestDetector\MaximumCount * @uses \Ergebnis\PHPUnit\SlowTestDetector\MaximumDuration * @uses \Ergebnis\PHPUnit\SlowTestDetector\SlowTest + * @uses \Ergebnis\PHPUnit\SlowTestDetector\SlowTestCount + * @uses \Ergebnis\PHPUnit\SlowTestDetector\SlowTestList * @uses \Ergebnis\PHPUnit\SlowTestDetector\TestDescription * @uses \Ergebnis\PHPUnit\SlowTestDetector\TestDuration * @uses \Ergebnis\PHPUnit\SlowTestDetector\TestIdentifier @@ -43,47 +47,44 @@ final class DefaultReporterTest extends Framework\TestCase { use Test\Util\Helper; - public function testReportReturnsEmptyStringWhenThereAreNoSlowTests() + public function testReportReturnsEmptyStringWhenSlowTestListIsEmpty() { $faker = self::faker(); + $slowTestList = SlowTestList::create(); + $reporter = new Reporter\DefaultReporter( new Formatter\DefaultDurationFormatter(), - MaximumDuration::fromDuration(Duration::fromMilliseconds($faker->numberBetween(0))), MaximumCount::fromCount(Count::fromInt($faker->numberBetween(1))) ); - $report = $reporter->report(); + $report = $reporter->report($slowTestList); self::assertSame('', $report); } /** - * @dataProvider provideExpectedReportMaximumDurationMaximumCountAndSlowTests - * - * @param list $slowTests + * @dataProvider provideExpectedReportMaximumCountAndSlowTestList */ - public function testReportReturnsReportWhenThereAreFewerSlowTestsThanMaximumCount( + public function testReportReturnsReportWhenSlowTestListHasFewerSlowTestsThanMaximumCount( string $expectedReport, - MaximumDuration $maximumDuration, MaximumCount $maximumCount, - array $slowTests + SlowTestList $slowTestList ) { $reporter = new Reporter\DefaultReporter( new Formatter\DefaultDurationFormatter(), - $maximumDuration, $maximumCount ); - $report = $reporter->report(...$slowTests); + $report = $reporter->report($slowTestList); self::assertSame($expectedReport, $report); } /** - * @return \Generator}> + * @return \Generator */ - public static function provideExpectedReportMaximumDurationMaximumCountAndSlowTests(): iterable + public static function provideExpectedReportMaximumCountAndSlowTestList(): iterable { $values = [ 'header-singular' => [ @@ -93,16 +94,15 @@ public static function provideExpectedReportMaximumDurationMaximumCountAndSlowTe 1. 0.300 (0.100) FooTest::test TXT , - MaximumDuration::fromDuration(Duration::fromMilliseconds(500)), MaximumCount::fromCount(Count::fromInt(1)), - [ + SlowTestList::create( SlowTest::create( TestIdentifier::fromString('FooTest::test'), TestDescription::fromString('FooTest::test'), TestDuration::fromDuration(Duration::fromMilliseconds(300)), MaximumDuration::fromDuration(Duration::fromMilliseconds(100)) - ), - ], + ) + ), ], 'header-plural' => [ <<<'TXT' @@ -112,9 +112,8 @@ public static function provideExpectedReportMaximumDurationMaximumCountAndSlowTe 2. 0.275 (0.100) BarTest::test TXT , - MaximumDuration::fromDuration(Duration::fromMilliseconds(500)), MaximumCount::fromCount(Count::fromInt(2)), - [ + SlowTestList::create( SlowTest::create( TestIdentifier::fromString('FooTest::test'), TestDescription::fromString('FooTest::test'), @@ -126,8 +125,8 @@ public static function provideExpectedReportMaximumDurationMaximumCountAndSlowTe TestDescription::fromString('BarTest::test'), TestDuration::fromDuration(Duration::fromMilliseconds(275)), MaximumDuration::fromDuration(Duration::fromMilliseconds(100)) - ), - ], + ) + ), ], 'list-sorted' => [ <<<'TXT' @@ -138,9 +137,8 @@ public static function provideExpectedReportMaximumDurationMaximumCountAndSlowTe 3. 0.250 (0.100) BazTest::test TXT , - MaximumDuration::fromDuration(Duration::fromMilliseconds(500)), MaximumCount::fromCount(Count::fromInt(3)), - [ + SlowTestList::create( SlowTest::create( TestIdentifier::fromString('FooTest::test'), TestDescription::fromString('FooTest::test'), @@ -158,8 +156,8 @@ public static function provideExpectedReportMaximumDurationMaximumCountAndSlowTe TestDescription::fromString('BazTest::test'), TestDuration::fromDuration(Duration::fromMilliseconds(250)), MaximumDuration::fromDuration(Duration::fromMilliseconds(100)) - ), - ], + ) + ), ], 'list-unsorted' => [ <<<'TXT' @@ -170,9 +168,8 @@ public static function provideExpectedReportMaximumDurationMaximumCountAndSlowTe 3. 0.250 (0.100) BazTest::test TXT , - MaximumDuration::fromDuration(Duration::fromMilliseconds(500)), MaximumCount::fromCount(Count::fromInt(3)), - [ + SlowTestList::create( SlowTest::create( TestIdentifier::fromString('BazTest::test'), TestDescription::fromString('BazTest::test'), @@ -190,8 +187,8 @@ public static function provideExpectedReportMaximumDurationMaximumCountAndSlowTe TestDescription::fromString('FooTest::test'), TestDuration::fromDuration(Duration::fromMilliseconds(300)), MaximumDuration::fromDuration(Duration::fromMilliseconds(100)) - ), - ], + ) + ), ], 'list-different-maximum-duration' => [ <<<'TXT' @@ -209,9 +206,8 @@ public static function provideExpectedReportMaximumDurationMaximumCountAndSlowTe 10. 0.110 ( 0.100) FredTest::test TXT , - MaximumDuration::fromDuration(Duration::fromMilliseconds(500)), MaximumCount::fromCount(Count::fromInt(10)), - [ + SlowTestList::create( SlowTest::create( TestIdentifier::fromString('FooTest::test'), TestDescription::fromString('FooTest::test'), @@ -271,8 +267,8 @@ public static function provideExpectedReportMaximumDurationMaximumCountAndSlowTe TestDescription::fromString('FredTest::test'), TestDuration::fromDuration(Duration::fromMilliseconds(110)), MaximumDuration::fromDuration(Duration::fromMilliseconds(100)) - ), - ], + ) + ), ], 'footer-singular' => [ <<<'TXT' @@ -283,9 +279,8 @@ public static function provideExpectedReportMaximumDurationMaximumCountAndSlowTe There is 1 additional slow test that is not listed here. TXT , - MaximumDuration::fromDuration(Duration::fromMilliseconds(500)), MaximumCount::fromCount(Count::fromInt(1)), - [ + SlowTestList::create( SlowTest::create( TestIdentifier::fromString('FooTest::test'), TestDescription::fromString('FooTest::test'), @@ -297,8 +292,8 @@ public static function provideExpectedReportMaximumDurationMaximumCountAndSlowTe TestDescription::fromString('BarTest::test'), TestDuration::fromDuration(Duration::fromMilliseconds(275)), MaximumDuration::fromDuration(Duration::fromMilliseconds(100)) - ), - ], + ) + ), ], 'footer-plural' => [ <<<'TXT' @@ -309,9 +304,8 @@ public static function provideExpectedReportMaximumDurationMaximumCountAndSlowTe There are 2 additional slow tests that are not listed here. TXT , - MaximumDuration::fromDuration(Duration::fromMilliseconds(500)), MaximumCount::fromCount(Count::fromInt(1)), - [ + SlowTestList::create( SlowTest::create( TestIdentifier::fromString('FooTest::test'), TestDescription::fromString('FooTest::test'), @@ -329,17 +323,16 @@ public static function provideExpectedReportMaximumDurationMaximumCountAndSlowTe TestDescription::fromString('BazTest::test'), TestDuration::fromDuration(Duration::fromMilliseconds(250)), MaximumDuration::fromDuration(Duration::fromMilliseconds(100)) - ), - ], + ) + ), ], ]; - foreach ($values as $key => list($expected, $maximumDuration, $maximumCount, $slowTests)) { + foreach ($values as $key => list($expected, $maximumCount, $slowTestList)) { yield $key => [ $expected, - $maximumDuration, $maximumCount, - $slowTests, + $slowTestList, ]; } } diff --git a/test/Unit/SlowTestCountTest.php b/test/Unit/SlowTestCountTest.php new file mode 100644 index 00000000..608f46e9 --- /dev/null +++ b/test/Unit/SlowTestCountTest.php @@ -0,0 +1,60 @@ +toCount()); + } + + public function testEqualsReturnsFalseWhenValueIsDifferent() + { + $faker = self::faker()->unique(); + + $one = SlowTestCount::fromCount(Count::fromInt($faker->numberBetween(0))); + $two = SlowTestCount::fromCount(Count::fromInt($faker->numberBetween(0))); + + self::assertFalse($one->equals($two)); + } + + public function testEqualsReturnsFalseWhenValueIsSame() + { + $count = Count::fromInt(self::faker()->numberBetween(0)); + + $one = SlowTestCount::fromCount($count); + $two = SlowTestCount::fromCount($count); + + self::assertTrue($one->equals($two)); + } +} diff --git a/test/Unit/SlowTestListTest.php b/test/Unit/SlowTestListTest.php new file mode 100644 index 00000000..2f3e0711 --- /dev/null +++ b/test/Unit/SlowTestListTest.php @@ -0,0 +1,267 @@ +word()), + TestDescription::fromString($faker->word()), + TestDuration::fromDuration(Duration::fromMilliseconds($faker->numberBetween(0))), + MaximumDuration::fromDuration(Duration::fromMilliseconds($faker->numberBetween(0))) + ); + }, \range(1, $faker->numberBetween(1, 10))); + + $slowTestList = SlowTestList::create(...$slowTests); + + self::assertSame($slowTests, $slowTestList->toArray()); + } + + public function testSlowTestCountReturnsCountOfSlowTests() + { + $faker = self::faker(); + + $slowTests = \array_map(static function () use ($faker): SlowTest { + return SlowTest::create( + TestIdentifier::fromString($faker->word()), + TestDescription::fromString($faker->word()), + TestDuration::fromDuration(Duration::fromMilliseconds($faker->numberBetween(0))), + MaximumDuration::fromDuration(Duration::fromMilliseconds($faker->numberBetween(0))) + ); + }, \range(1, $faker->numberBetween(1, 10))); + + $slowTestList = SlowTestList::create(...$slowTests); + + $expected = SlowTestCount::fromCount(Count::fromInt(\count($slowTests))); + + self::assertEquals($expected, $slowTestList->slowTestCount()); + } + + public function testFirstThrowsExceptionWhenSlowTestListIsEmpty() + { + $slowTestList = SlowTestList::create(); + + $this->expectException(Exception\SlowTestListIsEmpty::class); + + $slowTestList->first(); + } + + public function testFirstReturnsFirstSlowTestWhenSlowTestListIsNotEmpty() + { + $faker = self::faker(); + + $slowTests = \array_map(static function () use ($faker): SlowTest { + return SlowTest::create( + TestIdentifier::fromString($faker->word()), + TestDescription::fromString($faker->word()), + TestDuration::fromDuration(Duration::fromMilliseconds($faker->numberBetween(0))), + MaximumDuration::fromDuration(Duration::fromMilliseconds($faker->numberBetween(0))) + ); + }, \range(1, $faker->numberBetween(1, 10))); + + $slowTestList = SlowTestList::create(...$slowTests); + + $expected = \reset($slowTests); + + self::assertSame($expected, $slowTestList->first()); + } + + public function testIsEmptyReturnsTrueWhenSlowTestListIsEmpty() + { + $slowTestList = SlowTestList::create(); + + self::assertTrue($slowTestList->isEmpty()); + } + + public function testIsEmptyReturnsFalseWhenSlowTestListIsNotEmpty() + { + $faker = self::faker(); + + $slowTests = \array_map(static function () use ($faker): SlowTest { + return SlowTest::create( + TestIdentifier::fromString($faker->word()), + TestDescription::fromString($faker->word()), + TestDuration::fromDuration(Duration::fromMilliseconds($faker->numberBetween(0))), + MaximumDuration::fromDuration(Duration::fromMilliseconds($faker->numberBetween(0))) + ); + }, \range(1, $faker->numberBetween(1, 10))); + + $slowTestList = SlowTestList::create(...$slowTests); + + self::assertFalse($slowTestList->isEmpty()); + } + + public function testLimitReturnsSlowTestListWhenSlowTestListHasFewerSlowTests() + { + $faker = self::faker(); + + $maximumCount = MaximumCount::fromCount(Count::fromInt($faker->numberBetween(2, 10))); + + $slowTests = \array_map(static function () use ($faker): SlowTest { + return SlowTest::create( + TestIdentifier::fromString($faker->word()), + TestDescription::fromString($faker->word()), + TestDuration::fromDuration(Duration::fromMilliseconds($faker->numberBetween(0))), + MaximumDuration::fromDuration(Duration::fromMilliseconds($faker->numberBetween(0))) + ); + }, \range(1, $faker->numberBetween(1, $maximumCount->toCount()->toInt() - 1))); + + $slowTestList = SlowTestList::create(...$slowTests); + + $limited = $slowTestList->limit($maximumCount); + + self::assertNotSame($slowTestList, $limited); + + $expected = \array_slice( + $slowTests, + 0, + $maximumCount->toCount()->toInt() + ); + + self::assertEquals($expected, $limited->toArray()); + } + + public function testLimitReturnsSlowTestListWhenSlowTestListHasMoreSlowTests() + { + $faker = self::faker(); + + $maximumCount = MaximumCount::fromCount(Count::fromInt($faker->numberBetween(2, 10))); + + $slowTests = \array_map(static function () use ($faker): SlowTest { + return SlowTest::create( + TestIdentifier::fromString($faker->word()), + TestDescription::fromString($faker->word()), + TestDuration::fromDuration(Duration::fromMilliseconds($faker->numberBetween(0))), + MaximumDuration::fromDuration(Duration::fromMilliseconds($faker->numberBetween(0))) + ); + }, \range(1, $faker->numberBetween($maximumCount->toCount()->toInt() + 1, $maximumCount->toCount()->toInt() + 10))); + + $slowTestList = SlowTestList::create(...$slowTests); + + $limited = $slowTestList->limit($maximumCount); + + self::assertNotSame($slowTestList, $limited); + + $expected = \array_slice( + $slowTests, + 0, + $maximumCount->toCount()->toInt() + ); + + self::assertEquals($expected, $limited->toArray()); + } + + public function testSortByTestDurationDescendingReturnsSlowTestListWhereSlowTestsAreSortedByTestDurationDescending() + { + $faker = self::faker(); + + $durationComparator = new Comparator\DurationComparator(); + + $slowTests = \array_map(static function () use ($faker): SlowTest { + return SlowTest::create( + TestIdentifier::fromString($faker->word()), + TestDescription::fromString($faker->word()), + TestDuration::fromDuration(Duration::fromMilliseconds($faker->numberBetween(0))), + MaximumDuration::fromDuration(Duration::fromMilliseconds($faker->numberBetween(0))) + ); + }, \range(1, $faker->numberBetween(1, 10))); + + $slowTestList = SlowTestList::create(...$slowTests); + + $sortedByTestDurationDescending = $slowTestList->sortByTestDurationDescending(); + + self::assertNotSame($slowTestList, $sortedByTestDurationDescending); + + $expected = $slowTests; + + \usort($expected, static function (SlowTest $one, SlowTest $two) use ($durationComparator): int { + return $durationComparator->compare( + $two->testDuration()->toDuration(), + $one->testDuration()->toDuration() + ); + }); + + self::assertEquals($expected, $sortedByTestDurationDescending->toArray()); + } + + public function testSortByMaximumDurationDescendingReturnsSlowTestListWhereSlowTestsAreSortedByMaximumDurationDescending() + { + $faker = self::faker(); + + $durationComparator = new Comparator\DurationComparator(); + + $slowTests = \array_map(static function () use ($faker): SlowTest { + return SlowTest::create( + TestIdentifier::fromString($faker->word()), + TestDescription::fromString($faker->word()), + TestDuration::fromDuration(Duration::fromMilliseconds($faker->numberBetween(0))), + MaximumDuration::fromDuration(Duration::fromMilliseconds($faker->numberBetween(0))) + ); + }, \range(1, $faker->numberBetween(1, 10))); + + $slowTestList = SlowTestList::create(...$slowTests); + + $sortedByMaximumDurationDescending = $slowTestList->sortByMaximumDurationDescending(); + + self::assertNotSame($slowTestList, $sortedByMaximumDurationDescending); + + $expected = $slowTests; + + \usort($expected, static function (SlowTest $one, SlowTest $two) use ($durationComparator): int { + return $durationComparator->compare( + $two->maximumDuration()->toDuration(), + $one->maximumDuration()->toDuration() + ); + }); + + self::assertEquals($expected, $sortedByMaximumDurationDescending->toArray()); + } +}