Skip to content

Commit

Permalink
Merge pull request #23 from ergebnis/feature/collector
Browse files Browse the repository at this point in the history
Enhancement: Extract Collector
  • Loading branch information
ergebnis-bot committed Jan 24, 2021
2 parents 1b39847 + 3e5286a commit 6dc4bec
Show file tree
Hide file tree
Showing 7 changed files with 314 additions and 53 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ For a full diff see [`7afa59c...main`][7afa59c...main].
* Added `Comparator\DurationComparator` ([#18]), by [@localheinz]
* Added `SlowTestReporter` ([#19]), by [@localheinz]
* Extracted `TimeKeeper` ([#22]), by [@localheinz]
* Extracted `Collector` ([#23]), by [@localheinz]

### Changed

Expand All @@ -36,5 +37,6 @@ For a full diff see [`7afa59c...main`][7afa59c...main].
[#20]: https://github.com/ergebnis/phpunit-slow-test-detector/pull/20
[#21]: https://github.com/ergebnis/phpunit-slow-test-detector/pull/21
[#22]: https://github.com/ergebnis/phpunit-slow-test-detector/pull/22
[#23]: https://github.com/ergebnis/phpunit-slow-test-detector/pull/23

[@localheinz]: https://github.com/localheinz
63 changes: 63 additions & 0 deletions src/Collector.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<?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 Collector
{
/**
* @var array<string, SlowTest>
*/
private array $slowTests = [];

public function collect(SlowTest $slowTest): void
{
$key = self::key($slowTest->test());

if (\array_key_exists($key, $this->slowTests)) {
$previousSlowTest = $this->slowTests[$key];

if (!$slowTest->duration()->isGreaterThan($previousSlowTest->duration())) {
return;
}

$this->slowTests[$key] = $slowTest;

return;
}

$this->slowTests[$key] = $slowTest;
}

/**
* @phpstan-return list<SlowTest>
* @psalm-return list<SlowTest>
*
* @return array<int, SlowTest>
*/
public function collected(): array
{
return \array_values($this->slowTests);
}

private static function key(Event\Code\Test $test): string
{
return \sprintf(
'%s::%s',
$test->className(),
$test->methodNameWithDataSet(),
);
}
}
46 changes: 12 additions & 34 deletions src/SlowTestCollector.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,20 @@

final class SlowTestCollector
{
private TimeKeeper $timer;

private Event\Telemetry\Duration $maximumDuration;

/**
* @var array<string, SlowTest>
*/
private array $slowTests = [];
private TimeKeeper $timer;

public function __construct(TimeKeeper $timeKeeper, Event\Telemetry\Duration $maximumDuration)
{
$this->timer = $timeKeeper;
private Collector $collector;

public function __construct(
Event\Telemetry\Duration $maximumDuration,
TimeKeeper $timeKeeper,
Collector $collector
) {
$this->maximumDuration = $maximumDuration;
$this->timer = $timeKeeper;
$this->collector = $collector;
}

public function testPrepared(Event\Code\Test $test, Event\Telemetry\HRTime $preparedTime): void
Expand All @@ -56,21 +57,7 @@ public function testPassed(Event\Code\Test $test, Event\Telemetry\HRTime $passed
$duration
);

$key = self::key($test);

if (\array_key_exists($key, $this->slowTests)) {
$previousSlowTest = $this->slowTests[$key];

if (!$duration->isGreaterThan($previousSlowTest->duration())) {
return;
}

$this->slowTests[$key] = $slowTest;

return;
}

$this->slowTests[$key] = $slowTest;
$this->collector->collect($slowTest);
}

public function maximumDuration(): Event\Telemetry\Duration
Expand All @@ -86,15 +73,6 @@ public function maximumDuration(): Event\Telemetry\Duration
*/
public function slowTests(): array
{
return \array_values($this->slowTests);
}

private static function key(Event\Code\Test $test): string
{
return \sprintf(
'%s::%s',
$test->className(),
$test->methodNameWithDataSet(),
);
return $this->collector->collected();
}
}
203 changes: 203 additions & 0 deletions test/Unit/CollectorTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,203 @@
<?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;

use Ergebnis\PHPUnit\SlowTestDetector\Collector;
use Ergebnis\PHPUnit\SlowTestDetector\SlowTest;
use Ergebnis\PHPUnit\SlowTestDetector\Test\Fixture;
use Ergebnis\Test\Util;
use PHPUnit\Event;
use PHPUnit\Framework;

/**
* @internal
*
* @covers \Ergebnis\PHPUnit\SlowTestDetector\Collector
*
* @uses \Ergebnis\PHPUnit\SlowTestDetector\SlowTest
*/
final class CollectorTest extends Framework\TestCase
{
use Util\Helper;

public function testDefaults(): void
{
$collector = new Collector();

self::assertSame([], $collector->collected());
}

public function testCollectCollectsSlowTests(): void
{
$faker = self::faker();

$first = SlowTest::fromTestAndDuration(
new Event\Code\Test(
Fixture\ExampleTest::class,
'foo',
'foo with data set #123',
),
Event\Telemetry\Duration::fromSecondsAndNanoseconds(
$faker->numberBetween(),
$faker->numberBetween(0, 999_999_999)
)
);

$second = SlowTest::fromTestAndDuration(
new Event\Code\Test(
Fixture\ExampleTest::class,
'bar',
'bar',
),
Event\Telemetry\Duration::fromSecondsAndNanoseconds(
$faker->numberBetween(),
$faker->numberBetween(0, 999_999_999)
)
);

$third = SlowTest::fromTestAndDuration(
new Event\Code\Test(
Fixture\ExampleTest::class,
'baz',
'baz with data set "string"',
),
Event\Telemetry\Duration::fromSecondsAndNanoseconds(
$faker->numberBetween(),
$faker->numberBetween(0, 999_999_999)
)
);

$collector = new Collector();

$collector->collect($first);
$collector->collect($second);
$collector->collect($third);

$expected = [
$first,
$second,
$third,
];

self::assertSame($expected, $collector->collected());
}

public function testCollectDoesNotReplaceSlowTestWhenDurationIsLessThanPreviousSlowTest(): void
{
$faker = self::faker();

$first = SlowTest::fromTestAndDuration(
new Event\Code\Test(
Fixture\ExampleTest::class,
'foo',
'foo with data set #123',
),
Event\Telemetry\Duration::fromSecondsAndNanoseconds(
$faker->numberBetween(1),
$faker->numberBetween(0, 999_999_999)
)
);

$second = SlowTest::fromTestAndDuration(
new Event\Code\Test(
Fixture\ExampleTest::class,
'bar',
'bar',
),
Event\Telemetry\Duration::fromSecondsAndNanoseconds(
$faker->numberBetween(),
$faker->numberBetween(0, 999_999_999)
)
);

$thirdForSameTest = SlowTest::fromTestAndDuration(
new Event\Code\Test(
$first->test()->className(),
$first->test()->methodName(),
$first->test()->methodNameWithDataSet(),
),
Event\Telemetry\Duration::fromSecondsAndNanoseconds(
$faker->numberBetween(0, $first->duration()->seconds() - 1),
$faker->numberBetween(0, 999_999_999)
)
);

$collector = new Collector();

$collector->collect($first);
$collector->collect($second);
$collector->collect($thirdForSameTest);

$expected = [
$first,
$second,
];

self::assertSame($expected, $collector->collected());
}

public function testCollectReplacesSlowTestWhenDurationIsGreaterThanPreviousSlowTest(): void
{
$faker = self::faker();

$first = SlowTest::fromTestAndDuration(
new Event\Code\Test(
Fixture\ExampleTest::class,
'foo',
'foo with data set #123',
),
Event\Telemetry\Duration::fromSecondsAndNanoseconds(
$faker->numberBetween(),
$faker->numberBetween(0, 999_999_999)
)
);

$second = SlowTest::fromTestAndDuration(
new Event\Code\Test(
Fixture\ExampleTest::class,
'bar',
'bar',
),
Event\Telemetry\Duration::fromSecondsAndNanoseconds(
$faker->numberBetween(),
$faker->numberBetween(0, 999_999_999)
)
);

$thirdForSameTest = SlowTest::fromTestAndDuration(
new Event\Code\Test(
$first->test()->className(),
$first->test()->methodName(),
$first->test()->methodNameWithDataSet(),
),
Event\Telemetry\Duration::fromSecondsAndNanoseconds(
$faker->numberBetween($first->duration()->seconds() + 1),
$faker->numberBetween(0, 999_999_999)
)
);

$collector = new Collector();

$collector->collect($first);
$collector->collect($second);
$collector->collect($thirdForSameTest);

$expected = [
$thirdForSameTest,
$second,
];

self::assertSame($expected, $collector->collected());
}
}
Loading

0 comments on commit 6dc4bec

Please sign in to comment.