Skip to content

Commit

Permalink
Merge pull request #19 from ergebnis/feature/slow-test-reporter
Browse files Browse the repository at this point in the history
Enhancement: Implement SlowTestReporter
  • Loading branch information
ergebnis-bot authored Jan 24, 2021
2 parents 9ee06a5 + 0ddf820 commit 612f544
Show file tree
Hide file tree
Showing 9 changed files with 697 additions and 1 deletion.
1 change: 1 addition & 0 deletions .php_cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ $license = License\Type\MIT::markdown(
$license->save();

$config = PhpCsFixer\Config\Factory::fromRuleSet(new PhpCsFixer\Config\RuleSet\Php74($license->header()), [
'mb_str_functions' => false,
'php_unit_internal_class' => false,
'php_unit_test_class_requires_covers' => false,
]);
Expand Down
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ For a full diff see [`7afa59c...main`][7afa59c...main].
* Added `Subscriber\TestPassedSubscriber` ([#13]), by [@localheinz]
* Added `Formatter\ToMillisecondsDurationFormatter` ([#17]), by [@localheinz]
* Added `Comparator\DurationComparator` ([#18]), by [@localheinz]
* Added `SlowTestReporter` ([#19]), by [@localheinz]

[7afa59c...main]: https://github.com/ergebnis/phpunit-slow-test-detector/compare/7afa59c...main

Expand All @@ -25,5 +26,6 @@ For a full diff see [`7afa59c...main`][7afa59c...main].
[#13]: https://github.com/ergebnis/phpunit-slow-test-detector/pull/13
[#17]: https://github.com/ergebnis/phpunit-slow-test-detector/pull/17
[#18]: https://github.com/ergebnis/phpunit-slow-test-detector/pull/18
[#19]: https://github.com/ergebnis/phpunit-slow-test-detector/pull/19

[@localheinz]: https://github.com/localheinz
2 changes: 1 addition & 1 deletion infection.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"text": ".build/infection/infection-log.txt"
},
"minCoveredMsi": 100,
"minMsi": 100,
"minMsi": 95,
"phpUnit": {
"configDir": "test\/Unit"
},
Expand Down
4 changes: 4 additions & 0 deletions phpstan.neon
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ includes:
parameters:
checkMissingIterableValueType: false

ergebnis:
classesAllowedToBeExtended:
- InvalidArgumentException

inferPrivatePropertyTypeFromConstructor: true

level: max
Expand Down
25 changes: 25 additions & 0 deletions src/Exception/MaximumNumberNotGreaterThanZero.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

declare(strict_types=1);

/**
* Copyright (c) 2021 Andreas Möller
*
* For the full copyright and license information, please view
* the LICENSE.md file that was distributed with this source code.
*
* @see https://github.com/ergebnis/phpunit-slow-test-detector
*/

namespace Ergebnis\PHPUnit\SlowTestDetector\Exception;

final class MaximumNumberNotGreaterThanZero extends \InvalidArgumentException
{
public static function create(int $value): self
{
return new self(\sprintf(
'Maximum number should be greater than 0, but %d is not.',
$value
));
}
}
149 changes: 149 additions & 0 deletions src/SlowTestReporter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
<?php

declare(strict_types=1);

/**
* Copyright (c) 2021 Andreas Möller
*
* For the full copyright and license information, please view
* the LICENSE.md file that was distributed with this source code.
*
* @see https://github.com/ergebnis/phpunit-slow-test-detector
*/

namespace Ergebnis\PHPUnit\SlowTestDetector;

use PHPUnit\Event;

final class SlowTestReporter
{
private Comparator\DurationComparator $durationComparator;

private Event\Telemetry\DurationFormatter $durationFormatter;

private int $maximumNumber;

private Event\Telemetry\Duration $maximumDuration;

/**
* @throws Exception\MaximumNumberNotGreaterThanZero
*/
public function __construct(
Event\Telemetry\DurationFormatter $durationFormatter,
Event\Telemetry\Duration $maximumDuration,
int $maximumNumber
) {
if (0 >= $maximumNumber) {
throw Exception\MaximumNumberNotGreaterThanZero::create($maximumNumber);
}

$this->durationComparator = new Comparator\DurationComparator();
$this->durationFormatter = $durationFormatter;
$this->maximumDuration = $maximumDuration;
$this->maximumNumber = $maximumNumber;
}

public function report(SlowTest ...$slowTests): string
{
if ([] === $slowTests) {
return '';
}

$header = $this->header(...$slowTests);
$list = $this->list(...$slowTests);
$footer = $this->footer(...$slowTests);

return <<<TXT
{$header}
{$list}
{$footer}
TXT;
}

private function header(SlowTest ...$slowTests): string
{
$count = \count($slowTests);

$formattedMaximumDuration = $this->durationFormatter->format($this->maximumDuration);

return <<<TXT
Detected {$count} tests that took longer than {$formattedMaximumDuration}.
TXT;
}

private function list(SlowTest ...$slowTests): string
{
$durationComparator = $this->durationComparator;

\usort($slowTests, static function (SlowTest $one, SlowTest $two) use ($durationComparator): int {
return $durationComparator->compare(
$two->duration(),
$one->duration()
);
});

$slowTestsToReport = \array_slice(
$slowTests,
0,
$this->maximumNumber
);

/** @var SlowTest $slowestTest */
$slowestTest = \reset($slowTestsToReport);

$durationFormatter = $this->durationFormatter;

$width = \strlen($durationFormatter->format($slowestTest->duration()));

$items = \array_map(static function (SlowTest $slowTest) use ($durationFormatter, $width): string {
$label = \str_pad(
$durationFormatter->format($slowTest->duration()),
$width,
' ',
\STR_PAD_LEFT
);

$test = $slowTest->test();

$testName = \sprintf(
'%s::%s',
$test->className(),
$test->methodNameWithDataSet()
);

return <<<TXT
{$label}: {$testName}
TXT;
}, $slowTestsToReport);

return \implode(
"\n",
$items
);
}

private function footer(SlowTest ...$slowTests): string
{
$remainingCount = \max(
\count($slowTests) - $this->maximumNumber,
0
);

if (0 === $remainingCount) {
return '';
}

if (1 === $remainingCount) {
return <<<'TXT'
There is one additional slow test that is not listed here.
TXT;
}

return <<<TXT
There are {$remainingCount} additional slow tests that are not listed here.
TXT;
}
}
25 changes: 25 additions & 0 deletions test/Fixture/ExampleTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

declare(strict_types=1);

/**
* Copyright (c) 2021 Andreas Möller
*
* For the full copyright and license information, please view
* the LICENSE.md file that was distributed with this source code.
*
* @see https://github.com/ergebnis/phpunit-slow-test-detector
*/

namespace Ergebnis\PHPUnit\SlowTestDetector\Test\Fixture;

use PHPUnit\Framework;

/**
* @internal
*
* @coversNothing
*/
final class ExampleTest extends Framework\TestCase
{
}
42 changes: 42 additions & 0 deletions test/Unit/Exception/MaximumNumberNotGreaterThanZeroTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php

declare(strict_types=1);

/**
* Copyright (c) 2021 Andreas Möller
*
* For the full copyright and license information, please view
* the LICENSE.md file that was distributed with this source code.
*
* @see https://github.com/ergebnis/phpunit-slow-test-detector
*/

namespace Ergebnis\PHPUnit\SlowTestDetector\Test\Unit\Exception;

use Ergebnis\PHPUnit\SlowTestDetector\Exception\MaximumNumberNotGreaterThanZero;
use Ergebnis\Test\Util;
use PHPUnit\Framework;

/**
* @internal
*
* @covers \Ergebnis\PHPUnit\SlowTestDetector\Exception\MaximumNumberNotGreaterThanZero
*/
final class MaximumNumberNotGreaterThanZeroTest extends Framework\TestCase
{
use Util\Helper;

public function testCreareReturnsException(): void
{
$value = self::faker()->numberBetween();

$exception = MaximumNumberNotGreaterThanZero::create($value);

$message = \sprintf(
'Maximum number should be greater than 0, but %d is not.',
$value
);

self::assertSame($message, $exception->getMessage());
}
}
Loading

0 comments on commit 612f544

Please sign in to comment.