From 80a998fcad4161d43166a7da4e4306ec08246807 Mon Sep 17 00:00:00 2001 From: robiningelbrecht Date: Tue, 19 Sep 2023 15:21:23 +0200 Subject: [PATCH 1/4] Output execution time --- src/ConsoleOutput.php | 5 ++++- .../Application/ApplicationFinishedSubscriber.php | 7 ++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/ConsoleOutput.php b/src/ConsoleOutput.php index b19a1ad..0227ae0 100644 --- a/src/ConsoleOutput.php +++ b/src/ConsoleOutput.php @@ -4,6 +4,8 @@ use RobinIngelbrecht\PHPUnitCoverageTools\MinCoverage\MinCoverageResult; use RobinIngelbrecht\PHPUnitCoverageTools\MinCoverage\ResultStatus; +use SebastianBergmann\Timer\Duration; +use SebastianBergmann\Timer\ResourceUsageFormatter; use Symfony\Component\Console\Formatter\OutputFormatterStyle; use Symfony\Component\Console\Helper\Table; use Symfony\Component\Console\Helper\TableCell; @@ -39,7 +41,7 @@ public function __construct( /** * @param \RobinIngelbrecht\PHPUnitCoverageTools\MinCoverage\MinCoverageResult[] $results */ - public function print(array $results): void + public function print(array $results, Duration $duration): void { $statusWeights = array_map(fn (MinCoverageResult $result) => $result->getStatus()->getWeight(), $results); $finalStatus = ResultStatus::fromWeight(max($statusWeights)); @@ -99,5 +101,6 @@ public function print(array $results): void ], ]); $table->render(); + $this->output->writeln((new ResourceUsageFormatter())->resourceUsage($duration)); } } diff --git a/src/Subscriber/Application/ApplicationFinishedSubscriber.php b/src/Subscriber/Application/ApplicationFinishedSubscriber.php index 759e3b1..7aaebfb 100644 --- a/src/Subscriber/Application/ApplicationFinishedSubscriber.php +++ b/src/Subscriber/Application/ApplicationFinishedSubscriber.php @@ -14,6 +14,7 @@ use RobinIngelbrecht\PHPUnitCoverageTools\MinCoverage\MinCoverageRule; use RobinIngelbrecht\PHPUnitCoverageTools\MinCoverage\MinCoverageRules; use RobinIngelbrecht\PHPUnitCoverageTools\MinCoverage\ResultStatus; +use SebastianBergmann\Timer\Timer; use Symfony\Component\Console\Helper\FormatterHelper; final class ApplicationFinishedSubscriber extends FormatterHelper implements FinishedSubscriber @@ -29,6 +30,8 @@ public function __construct( public function notify(Finished $event): void { + $timer = new Timer(); + $timer->start(); /** @var string $reflectionFileName */ $reflectionFileName = (new \ReflectionClass(ClassLoader::class))->getFileName(); $absolutePathToCloverXml = dirname($reflectionFileName, 3).'/'.$this->relativePathToCloverXml; @@ -74,7 +77,9 @@ public function notify(Finished $event): void metrics: $metrics, metricTotal: $metricTotal, ); - $this->consoleOutput->print($results); + + $duration = $timer->stop(); + $this->consoleOutput->print($results, $duration); $needsExit = !empty(array_filter( $results, From 400325bc79eb65cd32bba824e792b18ecc10e9d6 Mon Sep 17 00:00:00 2001 From: robiningelbrecht Date: Tue, 19 Sep 2023 15:22:34 +0200 Subject: [PATCH 2/4] One less variable --- src/Subscriber/Application/ApplicationFinishedSubscriber.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Subscriber/Application/ApplicationFinishedSubscriber.php b/src/Subscriber/Application/ApplicationFinishedSubscriber.php index 7aaebfb..5ac5552 100644 --- a/src/Subscriber/Application/ApplicationFinishedSubscriber.php +++ b/src/Subscriber/Application/ApplicationFinishedSubscriber.php @@ -78,8 +78,7 @@ public function notify(Finished $event): void metricTotal: $metricTotal, ); - $duration = $timer->stop(); - $this->consoleOutput->print($results, $duration); + $this->consoleOutput->print($results, $timer->stop()); $needsExit = !empty(array_filter( $results, From 8ed1ab0da97b52c29020b4a254bb7aee54eaf92a Mon Sep 17 00:00:00 2001 From: robiningelbrecht Date: Wed, 20 Sep 2023 11:36:13 +0200 Subject: [PATCH 3/4] Render execution time the proper way --- src/ConsoleOutput.php | 7 +- .../ApplicationFinishedSubscriber.php | 25 +++-- src/Timer/SystemTimer.php | 29 +++++ src/Timer/Timer.php | 12 +++ tests/PausedTimer.php | 28 +++++ .../ApplicationFinishedSubscriberTest.php | 102 ++++++++++-------- ...hedSubscriberTest__testDivideByZero__1.txt | 3 +- ...berTest__testNotifyWhenCoverageIsOk__1.txt | 3 +- ...scriberTest__testNotifyWithAWarning__1.txt | 3 +- ..._testNotifyWithAtLeastOneFailedRule__1.txt | 3 +- ...criberTest__testNotifyWithOnlyTotal__1.txt | 3 +- ...t__testNotifyWithRulesThatDoNotExit__1.txt | 3 +- ...scriberTest__testNotifyWithoutTotal__1.txt | 3 +- 13 files changed, 167 insertions(+), 57 deletions(-) create mode 100644 src/Timer/SystemTimer.php create mode 100644 src/Timer/Timer.php create mode 100644 tests/PausedTimer.php diff --git a/src/ConsoleOutput.php b/src/ConsoleOutput.php index 0227ae0..6fffbb2 100644 --- a/src/ConsoleOutput.php +++ b/src/ConsoleOutput.php @@ -14,7 +14,7 @@ use Symfony\Component\Console\Helper\TableStyle; use Symfony\Component\Console\Output\OutputInterface; -class ConsoleOutput +final class ConsoleOutput { public function __construct( private readonly OutputInterface $output, @@ -38,6 +38,11 @@ public function __construct( ); } + public static function create(): self + { + return new self(new \Symfony\Component\Console\Output\ConsoleOutput()); + } + /** * @param \RobinIngelbrecht\PHPUnitCoverageTools\MinCoverage\MinCoverageResult[] $results */ diff --git a/src/Subscriber/Application/ApplicationFinishedSubscriber.php b/src/Subscriber/Application/ApplicationFinishedSubscriber.php index 5ac5552..8b5aba2 100644 --- a/src/Subscriber/Application/ApplicationFinishedSubscriber.php +++ b/src/Subscriber/Application/ApplicationFinishedSubscriber.php @@ -14,7 +14,8 @@ use RobinIngelbrecht\PHPUnitCoverageTools\MinCoverage\MinCoverageRule; use RobinIngelbrecht\PHPUnitCoverageTools\MinCoverage\MinCoverageRules; use RobinIngelbrecht\PHPUnitCoverageTools\MinCoverage\ResultStatus; -use SebastianBergmann\Timer\Timer; +use RobinIngelbrecht\PHPUnitCoverageTools\Timer\SystemTimer; +use RobinIngelbrecht\PHPUnitCoverageTools\Timer\Timer; use Symfony\Component\Console\Helper\FormatterHelper; final class ApplicationFinishedSubscriber extends FormatterHelper implements FinishedSubscriber @@ -25,13 +26,13 @@ public function __construct( private readonly bool $cleanUpCloverXml, private readonly Exitter $exitter, private readonly ConsoleOutput $consoleOutput, + private readonly Timer $timer, ) { } public function notify(Finished $event): void { - $timer = new Timer(); - $timer->start(); + $this->timer->start(); /** @var string $reflectionFileName */ $reflectionFileName = (new \ReflectionClass(ClassLoader::class))->getFileName(); $absolutePathToCloverXml = dirname($reflectionFileName, 3).'/'.$this->relativePathToCloverXml; @@ -51,7 +52,10 @@ public function notify(Finished $event): void if ($this->minCoverageRules->hasTotalRule() && \XMLReader::ELEMENT == $reader->nodeType && 'metrics' == $reader->name && 2 === $reader->depth) { /** @var \SimpleXMLElement $node */ $node = simplexml_load_string($reader->readOuterXml()); - $metricTotal = CoverageMetric::fromCloverXmlNode($node, MinCoverageRule::TOTAL); + $metricTotal = CoverageMetric::fromCloverXmlNode( + node: $node, + forClass: MinCoverageRule::TOTAL + ); continue; } if ($this->minCoverageRules->hasOtherRulesThanTotalRule() && \XMLReader::ELEMENT == $reader->nodeType && 'class' == $reader->name && 3 === $reader->depth) { @@ -59,7 +63,10 @@ public function notify(Finished $event): void $node = simplexml_load_string($reader->readInnerXml()); /** @var string $className */ $className = $reader->getAttribute('name'); - $metrics[] = CoverageMetric::fromCloverXmlNode($node, $className); + $metrics[] = CoverageMetric::fromCloverXmlNode( + node: $node, + forClass: $className + ); } } $reader->close(); @@ -78,7 +85,10 @@ public function notify(Finished $event): void metricTotal: $metricTotal, ); - $this->consoleOutput->print($results, $timer->stop()); + $this->consoleOutput->print( + results: $results, + duration: $this->timer->stop() + ); $needsExit = !empty(array_filter( $results, @@ -138,7 +148,8 @@ public static function fromConfigurationAndParameters( minCoverageRules: $rules, cleanUpCloverXml: $cleanUpCloverXml, exitter: new Exitter(), - consoleOutput: new ConsoleOutput(new \Symfony\Component\Console\Output\ConsoleOutput()), + consoleOutput: ConsoleOutput::create(), + timer: SystemTimer::create(), ); } } diff --git a/src/Timer/SystemTimer.php b/src/Timer/SystemTimer.php new file mode 100644 index 0000000..e7c7e55 --- /dev/null +++ b/src/Timer/SystemTimer.php @@ -0,0 +1,29 @@ +timer->start(); + } + + public function stop(): Duration + { + return $this->timer->stop(); + } + + public static function create(): self + { + return new self(new PhpUnitTimer()); + } +} diff --git a/src/Timer/Timer.php b/src/Timer/Timer.php new file mode 100644 index 0000000..c1d59ca --- /dev/null +++ b/src/Timer/Timer.php @@ -0,0 +1,12 @@ +duration; + } +} diff --git a/tests/Subscriber/Application/ApplicationFinishedSubscriberTest.php b/tests/Subscriber/Application/ApplicationFinishedSubscriberTest.php index 30de35c..48e4802 100644 --- a/tests/Subscriber/Application/ApplicationFinishedSubscriberTest.php +++ b/tests/Subscriber/Application/ApplicationFinishedSubscriberTest.php @@ -9,6 +9,7 @@ use PHPUnit\Event\Telemetry\Info; use PHPUnit\Event\Telemetry\MemoryUsage; use PHPUnit\Event\Telemetry\Snapshot; +use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use PHPUnit\Runner\Extension\ParameterCollection; use PHPUnit\TextUI\Configuration\Builder; @@ -16,19 +17,32 @@ use RobinIngelbrecht\PHPUnitCoverageTools\Exitter; use RobinIngelbrecht\PHPUnitCoverageTools\MinCoverage\MinCoverageRules; use RobinIngelbrecht\PHPUnitCoverageTools\Subscriber\Application\ApplicationFinishedSubscriber; +use RobinIngelbrecht\PHPUnitCoverageTools\Timer\SystemTimer; +use RobinIngelbrecht\PHPUnitCoverageTools\Timer\Timer; use Spatie\Snapshots\MatchesSnapshots; +use Tests\PausedTimer; use Tests\SpyOutput; class ApplicationFinishedSubscriberTest extends TestCase { use MatchesSnapshots; + private MockObject $exitter; + private Timer $timer; + + protected function setUp(): void + { + parent::setUp(); + + $this->exitter = $this->createMock(Exitter::class); + $this->timer = PausedTimer::withDuration(\SebastianBergmann\Timer\Duration::fromMicroseconds(350123)); + } + public function testNotifyWithAtLeastOneFailedRule(): void { - $exitter = $this->createMock(Exitter::class); $spyOutput = new SpyOutput(); - $exitter + $this->exitter ->expects($this->once()) ->method('exit'); @@ -36,8 +50,9 @@ public function testNotifyWithAtLeastOneFailedRule(): void relativePathToCloverXml: 'tests/clover.xml', minCoverageRules: MinCoverageRules::fromConfigFile('tests/Subscriber/Application/min-coverage-rules-with-failed-rule.php'), cleanUpCloverXml: false, - exitter: $exitter, + exitter: $this->exitter, consoleOutput: new ConsoleOutput($spyOutput), + timer: $this->timer, ); $subscriber->notify(event: new Finished( @@ -61,10 +76,9 @@ public function testNotifyWithAtLeastOneFailedRule(): void public function testNotifyWithAWarning(): void { - $exitter = $this->createMock(Exitter::class); $spyOutput = new SpyOutput(); - $exitter + $this->exitter ->expects($this->never()) ->method('exit'); @@ -72,8 +86,9 @@ public function testNotifyWithAWarning(): void relativePathToCloverXml: 'tests/clover.xml', minCoverageRules: MinCoverageRules::fromConfigFile('tests/Subscriber/Application/min-coverage-rules-with-warning.php'), cleanUpCloverXml: false, - exitter: $exitter, + exitter: $this->exitter, consoleOutput: new ConsoleOutput($spyOutput), + timer: $this->timer, ); $subscriber->notify(event: new Finished( @@ -97,10 +112,9 @@ public function testNotifyWithAWarning(): void public function testNotifyWhenCoverageIsOk(): void { - $exitter = $this->createMock(Exitter::class); $spyOutput = new SpyOutput(); - $exitter + $this->exitter ->expects($this->never()) ->method('exit'); @@ -108,8 +122,9 @@ public function testNotifyWhenCoverageIsOk(): void relativePathToCloverXml: 'tests/clover.xml', minCoverageRules: MinCoverageRules::fromConfigFile('tests/Subscriber/Application/min-coverage-rules-success.php'), cleanUpCloverXml: false, - exitter: $exitter, + exitter: $this->exitter, consoleOutput: new ConsoleOutput($spyOutput), + timer: $this->timer, ); $subscriber->notify(event: new Finished( @@ -133,10 +148,9 @@ public function testNotifyWhenCoverageIsOk(): void public function testNotifyWithOnlyTotal(): void { - $exitter = $this->createMock(Exitter::class); $spyOutput = new SpyOutput(); - $exitter + $this->exitter ->expects($this->never()) ->method('exit'); @@ -144,8 +158,9 @@ public function testNotifyWithOnlyTotal(): void relativePathToCloverXml: 'tests/clover.xml', minCoverageRules: MinCoverageRules::fromConfigFile('tests/Subscriber/Application/min-coverage-rules-total-only.php'), cleanUpCloverXml: false, - exitter: $exitter, + exitter: $this->exitter, consoleOutput: new ConsoleOutput($spyOutput), + timer: $this->timer, ); $subscriber->notify(event: new Finished( @@ -169,10 +184,9 @@ public function testNotifyWithOnlyTotal(): void public function testNotifyWithoutTotal(): void { - $exitter = $this->createMock(Exitter::class); $spyOutput = new SpyOutput(); - $exitter + $this->exitter ->expects($this->never()) ->method('exit'); @@ -180,8 +194,9 @@ public function testNotifyWithoutTotal(): void relativePathToCloverXml: 'tests/clover.xml', minCoverageRules: MinCoverageRules::fromConfigFile('tests/Subscriber/Application/min-coverage-rules-without-total.php'), cleanUpCloverXml: false, - exitter: $exitter, + exitter: $this->exitter, consoleOutput: new ConsoleOutput($spyOutput), + timer: $this->timer, ); $subscriber->notify(event: new Finished( @@ -205,10 +220,9 @@ public function testNotifyWithoutTotal(): void public function testNotifyWithRulesThatDoNotExit(): void { - $exitter = $this->createMock(Exitter::class); $spyOutput = new SpyOutput(); - $exitter + $this->exitter ->expects($this->never()) ->method('exit'); @@ -216,8 +230,9 @@ public function testNotifyWithRulesThatDoNotExit(): void relativePathToCloverXml: 'tests/clover.xml', minCoverageRules: MinCoverageRules::fromConfigFile('tests/Subscriber/Application/min-coverage-rules-no-exit.php'), cleanUpCloverXml: false, - exitter: $exitter, + exitter: $this->exitter, consoleOutput: new ConsoleOutput($spyOutput), + timer: $this->timer, ); $subscriber->notify(event: new Finished( @@ -241,10 +256,9 @@ public function testNotifyWithRulesThatDoNotExit(): void public function testDivideByZero(): void { - $exitter = $this->createMock(Exitter::class); $spyOutput = new SpyOutput(); - $exitter + $this->exitter ->expects($this->never()) ->method('exit'); @@ -252,8 +266,9 @@ public function testDivideByZero(): void relativePathToCloverXml: 'tests/clover-test-divide-by-zero.xml', minCoverageRules: MinCoverageRules::fromInt(100, true), cleanUpCloverXml: false, - exitter: $exitter, + exitter: $this->exitter, consoleOutput: new ConsoleOutput($spyOutput), + timer: $this->timer, ); $subscriber->notify(event: new Finished( @@ -277,10 +292,9 @@ public function testDivideByZero(): void public function testNotifyWithNonExistingCloverFile(): void { - $exitter = $this->createMock(Exitter::class); $spyOutput = new SpyOutput(); - $exitter + $this->exitter ->expects($this->never()) ->method('exit'); @@ -288,8 +302,9 @@ public function testNotifyWithNonExistingCloverFile(): void relativePathToCloverXml: 'tests/clover-wrong.xml', minCoverageRules: MinCoverageRules::fromConfigFile('tests/Subscriber/Application/min-coverage-rules-success.php'), cleanUpCloverXml: false, - exitter: $exitter, + exitter: $this->exitter, consoleOutput: new ConsoleOutput($spyOutput), + timer: $this->timer, ); $subscriber->notify(event: new Finished( @@ -313,10 +328,9 @@ public function testNotifyWithNonExistingCloverFile(): void public function testNotifyWithInvalidCloverFile(): void { - $exitter = $this->createMock(Exitter::class); $spyOutput = new SpyOutput(); - $exitter + $this->exitter ->expects($this->never()) ->method('exit'); @@ -324,8 +338,9 @@ public function testNotifyWithInvalidCloverFile(): void relativePathToCloverXml: 'tests/clover-invalid.xml', minCoverageRules: MinCoverageRules::fromConfigFile('tests/Subscriber/Application/min-coverage-rules-success.php'), cleanUpCloverXml: false, - exitter: $exitter, + exitter: $this->exitter, consoleOutput: new ConsoleOutput($spyOutput), + timer: $this->timer, ); $this->expectException(\RuntimeException::class); @@ -352,10 +367,9 @@ public function testNotifyWithCleanUpCloverFile(): void { copy(dirname(__DIR__, 2).'/clover.xml', dirname(__DIR__, 2).'/clover-to-delete.xml'); - $exitter = $this->createMock(Exitter::class); $spyOutput = new SpyOutput(); - $exitter + $this->exitter ->expects($this->once()) ->method('exit'); @@ -363,8 +377,9 @@ public function testNotifyWithCleanUpCloverFile(): void relativePathToCloverXml: 'tests/clover-to-delete.xml', minCoverageRules: MinCoverageRules::fromConfigFile('tests/Subscriber/Application/min-coverage-rules-with-failed-rule.php'), cleanUpCloverXml: true, - exitter: $exitter, + exitter: $this->exitter, consoleOutput: new ConsoleOutput($spyOutput), + timer: $this->timer, ); $subscriber->notify(event: new Finished( @@ -388,10 +403,9 @@ public function testNotifyWithCleanUpCloverFile(): void public function testNotifyWithDuplicatePatterns(): void { - $exitter = $this->createMock(Exitter::class); $spyOutput = new SpyOutput(); - $exitter + $this->exitter ->expects($this->never()) ->method('exit'); @@ -402,17 +416,17 @@ public function testNotifyWithDuplicatePatterns(): void relativePathToCloverXml: 'tests/clover.xml', minCoverageRules: MinCoverageRules::fromConfigFile('tests/Subscriber/Application/min-coverage-rules-with-duplicates.php'), cleanUpCloverXml: false, - exitter: $exitter, + exitter: $this->exitter, consoleOutput: new ConsoleOutput($spyOutput), + timer: $this->timer, ); } public function testNotifyWithInvalidRules(): void { - $exitter = $this->createMock(Exitter::class); $spyOutput = new SpyOutput(); - $exitter + $this->exitter ->expects($this->never()) ->method('exit'); @@ -423,17 +437,17 @@ public function testNotifyWithInvalidRules(): void relativePathToCloverXml: 'tests/clover.xml', minCoverageRules: MinCoverageRules::fromConfigFile('tests/Subscriber/Application/min-coverage-rules-invalid.php'), cleanUpCloverXml: false, - exitter: $exitter, + exitter: $this->exitter, consoleOutput: new ConsoleOutput($spyOutput), + timer: $this->timer, ); } public function testNotifyWithInvalidRuleInstances(): void { - $exitter = $this->createMock(Exitter::class); $spyOutput = new SpyOutput(); - $exitter + $this->exitter ->expects($this->never()) ->method('exit'); @@ -444,8 +458,9 @@ public function testNotifyWithInvalidRuleInstances(): void relativePathToCloverXml: 'tests/clover.xml', minCoverageRules: MinCoverageRules::fromConfigFile('tests/Subscriber/Application/min-coverage-invalid-rule-instances.php'), cleanUpCloverXml: false, - exitter: $exitter, + exitter: $this->exitter, consoleOutput: new ConsoleOutput($spyOutput), + timer: $this->timer, ); } @@ -457,7 +472,8 @@ public function testFromConfigurationAndParameters(): void minCoverageRules: MinCoverageRules::fromInt(90, false), cleanUpCloverXml: true, exitter: new Exitter(), - consoleOutput: new ConsoleOutput(new \Symfony\Component\Console\Output\ConsoleOutput()), + consoleOutput: ConsoleOutput::create(), + timer: SystemTimer::create(), ), ApplicationFinishedSubscriber::fromConfigurationAndParameters( (new Builder())->build([ @@ -477,7 +493,8 @@ public function testFromConfigurationAndParameters2(): void minCoverageRules: MinCoverageRules::fromInt(90, true), cleanUpCloverXml: true, exitter: new Exitter(), - consoleOutput: new ConsoleOutput(new \Symfony\Component\Console\Output\ConsoleOutput()), + consoleOutput: ConsoleOutput::create(), + timer: SystemTimer::create(), ), ApplicationFinishedSubscriber::fromConfigurationAndParameters( (new Builder())->build([ @@ -499,7 +516,8 @@ public function testFromConfigurationAndParametersFromFile(): void minCoverageRules: MinCoverageRules::fromConfigFile('tests/Subscriber/Application/min-coverage-rules-success.php'), cleanUpCloverXml: false, exitter: new Exitter(), - consoleOutput: new ConsoleOutput(new \Symfony\Component\Console\Output\ConsoleOutput()), + consoleOutput: ConsoleOutput::create(), + timer: SystemTimer::create(), ), actual: ApplicationFinishedSubscriber::fromConfigurationAndParameters( configuration: (new Builder())->build([ diff --git a/tests/Subscriber/Application/__snapshots__/ApplicationFinishedSubscriberTest__testDivideByZero__1.txt b/tests/Subscriber/Application/__snapshots__/ApplicationFinishedSubscriberTest__testDivideByZero__1.txt index 75fc4e5..d6c589c 100644 --- a/tests/Subscriber/Application/__snapshots__/ApplicationFinishedSubscriberTest__testDivideByZero__1.txt +++ b/tests/Subscriber/Application/__snapshots__/ApplicationFinishedSubscriberTest__testDivideByZero__1.txt @@ -6,4 +6,5 @@ | Total | 100% | 0% | No lines to track...? | Yes | +-----------------------+------------+----------+-----------------------+-------------+ | There was at least one pattern that did not match any covered classes. Please consider removing them. | -+-----------------------+------------+----------+-----------------------+-------------+ \ No newline at end of file ++-----------------------+------------+----------+-----------------------+-------------+ +Time: 00:00.350, Memory: 12.00 MB \ No newline at end of file diff --git a/tests/Subscriber/Application/__snapshots__/ApplicationFinishedSubscriberTest__testNotifyWhenCoverageIsOk__1.txt b/tests/Subscriber/Application/__snapshots__/ApplicationFinishedSubscriberTest__testNotifyWhenCoverageIsOk__1.txt index 4ba610e..aac31d2 100644 --- a/tests/Subscriber/Application/__snapshots__/ApplicationFinishedSubscriberTest__testNotifyWhenCoverageIsOk__1.txt +++ b/tests/Subscriber/Application/__snapshots__/ApplicationFinishedSubscriberTest__testNotifyWhenCoverageIsOk__1.txt @@ -7,4 +7,5 @@ | Total | 20% | 28.57% | 30 of 105 lines covered | Yes | +--------------------------------------------------------+------------+----------+-------------------------+-------------+ | All minimum code coverage rules passed, give yourself a pat on the back! | -+--------------------------------------------------------+------------+----------+-------------------------+-------------+ \ No newline at end of file ++--------------------------------------------------------+------------+----------+-------------------------+-------------+ +Time: 00:00.350, Memory: 12.00 MB \ No newline at end of file diff --git a/tests/Subscriber/Application/__snapshots__/ApplicationFinishedSubscriberTest__testNotifyWithAWarning__1.txt b/tests/Subscriber/Application/__snapshots__/ApplicationFinishedSubscriberTest__testNotifyWithAWarning__1.txt index 8f2b462..d8cff0d 100644 --- a/tests/Subscriber/Application/__snapshots__/ApplicationFinishedSubscriberTest__testNotifyWithAWarning__1.txt +++ b/tests/Subscriber/Application/__snapshots__/ApplicationFinishedSubscriberTest__testNotifyWithAWarning__1.txt @@ -7,4 +7,5 @@ | Total | 20% | 28.57% | 30 of 105 lines covered | Yes | +---------------------------------------+------------+----------+-------------------------+-------------+ | There was at least one pattern that did not match any covered classes. Please consider removing them. | -+---------------------------------------+------------+----------+-------------------------+-------------+ \ No newline at end of file ++---------------------------------------+------------+----------+-------------------------+-------------+ +Time: 00:00.350, Memory: 12.00 MB \ No newline at end of file diff --git a/tests/Subscriber/Application/__snapshots__/ApplicationFinishedSubscriberTest__testNotifyWithAtLeastOneFailedRule__1.txt b/tests/Subscriber/Application/__snapshots__/ApplicationFinishedSubscriberTest__testNotifyWithAtLeastOneFailedRule__1.txt index 19aa8c0..8154758 100644 --- a/tests/Subscriber/Application/__snapshots__/ApplicationFinishedSubscriberTest__testNotifyWithAtLeastOneFailedRule__1.txt +++ b/tests/Subscriber/Application/__snapshots__/ApplicationFinishedSubscriberTest__testNotifyWithAtLeastOneFailedRule__1.txt @@ -9,4 +9,5 @@ | Total | 20% | 28.57% | 30 of 105 lines covered | Yes | +--------------------------------------------------------------------------------------------+------------+----------+-------------------------+------------+ | Not all minimum code coverage rules passed, please try again... :) | -+--------------------------------------------------------------------------------------------+------------+----------+-------------------------+------------+ \ No newline at end of file ++--------------------------------------------------------------------------------------------+------------+----------+-------------------------+------------+ +Time: 00:00.350, Memory: 12.00 MB \ No newline at end of file diff --git a/tests/Subscriber/Application/__snapshots__/ApplicationFinishedSubscriberTest__testNotifyWithOnlyTotal__1.txt b/tests/Subscriber/Application/__snapshots__/ApplicationFinishedSubscriberTest__testNotifyWithOnlyTotal__1.txt index ac7ba24..93a11f6 100644 --- a/tests/Subscriber/Application/__snapshots__/ApplicationFinishedSubscriberTest__testNotifyWithOnlyTotal__1.txt +++ b/tests/Subscriber/Application/__snapshots__/ApplicationFinishedSubscriberTest__testNotifyWithOnlyTotal__1.txt @@ -6,4 +6,5 @@ | Total | 20% | 28.57% | 30 of 105 lines covered | Yes | +-----------------+------------+----------+-------------------------+-------------+ | All minimum code coverage rules passed, give yourself a pat on the back! | -+-----------------+------------+----------+-------------------------+-------------+ \ No newline at end of file ++-----------------+------------+----------+-------------------------+-------------+ +Time: 00:00.350, Memory: 12.00 MB \ No newline at end of file diff --git a/tests/Subscriber/Application/__snapshots__/ApplicationFinishedSubscriberTest__testNotifyWithRulesThatDoNotExit__1.txt b/tests/Subscriber/Application/__snapshots__/ApplicationFinishedSubscriberTest__testNotifyWithRulesThatDoNotExit__1.txt index dfb9bc4..7b768fc 100644 --- a/tests/Subscriber/Application/__snapshots__/ApplicationFinishedSubscriberTest__testNotifyWithRulesThatDoNotExit__1.txt +++ b/tests/Subscriber/Application/__snapshots__/ApplicationFinishedSubscriberTest__testNotifyWithRulesThatDoNotExit__1.txt @@ -9,4 +9,5 @@ | Total | 20% | 28.57% | 30 of 105 lines covered | No | +--------------------------------------------------------------------------------------------+------------+----------+-------------------------+------------+ | Not all minimum code coverage rules passed, please try again... :) | -+--------------------------------------------------------------------------------------------+------------+----------+-------------------------+------------+ \ No newline at end of file ++--------------------------------------------------------------------------------------------+------------+----------+-------------------------+------------+ +Time: 00:00.350, Memory: 12.00 MB \ No newline at end of file diff --git a/tests/Subscriber/Application/__snapshots__/ApplicationFinishedSubscriberTest__testNotifyWithoutTotal__1.txt b/tests/Subscriber/Application/__snapshots__/ApplicationFinishedSubscriberTest__testNotifyWithoutTotal__1.txt index a636d60..9dfb722 100644 --- a/tests/Subscriber/Application/__snapshots__/ApplicationFinishedSubscriberTest__testNotifyWithoutTotal__1.txt +++ b/tests/Subscriber/Application/__snapshots__/ApplicationFinishedSubscriberTest__testNotifyWithoutTotal__1.txt @@ -6,4 +6,5 @@ | RobinIngelbrecht\PHPUnitCoverageTools\PhpUnitExtension | 100% | 100% | 12 of 12 lines covered | Yes | +--------------------------------------------------------+------------+----------+------------------------+-------------+ | All minimum code coverage rules passed, give yourself a pat on the back! | -+--------------------------------------------------------+------------+----------+------------------------+-------------+ \ No newline at end of file ++--------------------------------------------------------+------------+----------+------------------------+-------------+ +Time: 00:00.350, Memory: 12.00 MB \ No newline at end of file From 1c35b19fa041d1f87e70e779c73124e1f7ef584e Mon Sep 17 00:00:00 2001 From: robiningelbrecht Date: Wed, 20 Sep 2023 12:03:32 +0200 Subject: [PATCH 4/4] Abstract the shit out of everything --- phpunit.xml.dist | 3 - src/ConsoleOutput.php | 11 ++- src/Exitter.php | 3 + src/Timer/ResourceUsageFormatter.php | 12 +++ src/Timer/SystemResourceUsageFormatter.php | 35 +++++++++ src/Timer/SystemTimer.php | 16 ++-- tests/FixedResourceUsageFormatter.php | 36 +++++++++ .../ApplicationFinishedSubscriberTest.php | 74 +++++++------------ 8 files changed, 132 insertions(+), 58 deletions(-) create mode 100644 src/Timer/ResourceUsageFormatter.php create mode 100644 src/Timer/SystemResourceUsageFormatter.php create mode 100644 tests/FixedResourceUsageFormatter.php diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 5c07df1..b3189fc 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -18,8 +18,5 @@ src - - src/Exitter.php - diff --git a/src/ConsoleOutput.php b/src/ConsoleOutput.php index 6fffbb2..6e7652d 100644 --- a/src/ConsoleOutput.php +++ b/src/ConsoleOutput.php @@ -4,8 +4,9 @@ use RobinIngelbrecht\PHPUnitCoverageTools\MinCoverage\MinCoverageResult; use RobinIngelbrecht\PHPUnitCoverageTools\MinCoverage\ResultStatus; +use RobinIngelbrecht\PHPUnitCoverageTools\Timer\ResourceUsageFormatter; +use RobinIngelbrecht\PHPUnitCoverageTools\Timer\SystemResourceUsageFormatter; use SebastianBergmann\Timer\Duration; -use SebastianBergmann\Timer\ResourceUsageFormatter; use Symfony\Component\Console\Formatter\OutputFormatterStyle; use Symfony\Component\Console\Helper\Table; use Symfony\Component\Console\Helper\TableCell; @@ -18,6 +19,7 @@ final class ConsoleOutput { public function __construct( private readonly OutputInterface $output, + private readonly ResourceUsageFormatter $resourceUsageFormatter, ) { $this->output->setDecorated(true); $this->output->getFormatter()->setStyle( @@ -40,7 +42,10 @@ public function __construct( public static function create(): self { - return new self(new \Symfony\Component\Console\Output\ConsoleOutput()); + return new self( + output: new \Symfony\Component\Console\Output\ConsoleOutput(), + resourceUsageFormatter: SystemResourceUsageFormatter::create() + ); } /** @@ -106,6 +111,6 @@ public function print(array $results, Duration $duration): void ], ]); $table->render(); - $this->output->writeln((new ResourceUsageFormatter())->resourceUsage($duration)); + $this->output->writeln($this->resourceUsageFormatter->resourceUsage($duration)); } } diff --git a/src/Exitter.php b/src/Exitter.php index d277a85..c548c0e 100644 --- a/src/Exitter.php +++ b/src/Exitter.php @@ -2,6 +2,9 @@ namespace RobinIngelbrecht\PHPUnitCoverageTools; +/** + * @codeCoverageIgnore + */ class Exitter { public function exit(): void diff --git a/src/Timer/ResourceUsageFormatter.php b/src/Timer/ResourceUsageFormatter.php new file mode 100644 index 0000000..f84d9ae --- /dev/null +++ b/src/Timer/ResourceUsageFormatter.php @@ -0,0 +1,12 @@ +resourceUsageFormatter->resourceUsage($duration); + } + + /** + * @codeCoverageIgnore + */ + public function resourceUsageSinceStartOfRequest(): string + { + return $this->resourceUsageFormatter->resourceUsageSinceStartOfRequest(); + } +} diff --git a/src/Timer/SystemTimer.php b/src/Timer/SystemTimer.php index e7c7e55..160e81f 100644 --- a/src/Timer/SystemTimer.php +++ b/src/Timer/SystemTimer.php @@ -12,18 +12,24 @@ private function __construct( ) { } + public static function create(): self + { + return new self(new PhpUnitTimer()); + } + + /** + * @codeCoverageIgnore + */ public function start(): void { $this->timer->start(); } + /** + * @codeCoverageIgnore + */ public function stop(): Duration { return $this->timer->stop(); } - - public static function create(): self - { - return new self(new PhpUnitTimer()); - } } diff --git a/tests/FixedResourceUsageFormatter.php b/tests/FixedResourceUsageFormatter.php new file mode 100644 index 0000000..95acb07 --- /dev/null +++ b/tests/FixedResourceUsageFormatter.php @@ -0,0 +1,36 @@ +asString(), + number_format($this->usageInMb, 2, '.', ''), + ); + } + + public function resourceUsageSinceStartOfRequest(): string + { + return sprintf( + 'Time: 00:00.350, Memory: %s MB', + number_format($this->usageInMb, 2, '.', ''), + ); + } +} diff --git a/tests/Subscriber/Application/ApplicationFinishedSubscriberTest.php b/tests/Subscriber/Application/ApplicationFinishedSubscriberTest.php index 48e4802..8721ce3 100644 --- a/tests/Subscriber/Application/ApplicationFinishedSubscriberTest.php +++ b/tests/Subscriber/Application/ApplicationFinishedSubscriberTest.php @@ -17,9 +17,11 @@ use RobinIngelbrecht\PHPUnitCoverageTools\Exitter; use RobinIngelbrecht\PHPUnitCoverageTools\MinCoverage\MinCoverageRules; use RobinIngelbrecht\PHPUnitCoverageTools\Subscriber\Application\ApplicationFinishedSubscriber; +use RobinIngelbrecht\PHPUnitCoverageTools\Timer\ResourceUsageFormatter; use RobinIngelbrecht\PHPUnitCoverageTools\Timer\SystemTimer; use RobinIngelbrecht\PHPUnitCoverageTools\Timer\Timer; use Spatie\Snapshots\MatchesSnapshots; +use Tests\FixedResourceUsageFormatter; use Tests\PausedTimer; use Tests\SpyOutput; @@ -29,19 +31,21 @@ class ApplicationFinishedSubscriberTest extends TestCase private MockObject $exitter; private Timer $timer; + private ResourceUsageFormatter $resourceUsageFormatter; + private SpyOutput $output; protected function setUp(): void { parent::setUp(); $this->exitter = $this->createMock(Exitter::class); + $this->output = new SpyOutput(); $this->timer = PausedTimer::withDuration(\SebastianBergmann\Timer\Duration::fromMicroseconds(350123)); + $this->resourceUsageFormatter = FixedResourceUsageFormatter::withUsageInMb(12.00); } public function testNotifyWithAtLeastOneFailedRule(): void { - $spyOutput = new SpyOutput(); - $this->exitter ->expects($this->once()) ->method('exit'); @@ -51,7 +55,7 @@ public function testNotifyWithAtLeastOneFailedRule(): void minCoverageRules: MinCoverageRules::fromConfigFile('tests/Subscriber/Application/min-coverage-rules-with-failed-rule.php'), cleanUpCloverXml: false, exitter: $this->exitter, - consoleOutput: new ConsoleOutput($spyOutput), + consoleOutput: new ConsoleOutput($this->output, $this->resourceUsageFormatter), timer: $this->timer, ); @@ -71,13 +75,11 @@ public function testNotifyWithAtLeastOneFailedRule(): void 0 )); - $this->assertMatchesTextSnapshot($spyOutput); + $this->assertMatchesTextSnapshot($this->output); } public function testNotifyWithAWarning(): void { - $spyOutput = new SpyOutput(); - $this->exitter ->expects($this->never()) ->method('exit'); @@ -87,7 +89,7 @@ public function testNotifyWithAWarning(): void minCoverageRules: MinCoverageRules::fromConfigFile('tests/Subscriber/Application/min-coverage-rules-with-warning.php'), cleanUpCloverXml: false, exitter: $this->exitter, - consoleOutput: new ConsoleOutput($spyOutput), + consoleOutput: new ConsoleOutput($this->output, $this->resourceUsageFormatter), timer: $this->timer, ); @@ -107,13 +109,11 @@ public function testNotifyWithAWarning(): void 0 )); - $this->assertMatchesTextSnapshot($spyOutput); + $this->assertMatchesTextSnapshot($this->output); } public function testNotifyWhenCoverageIsOk(): void { - $spyOutput = new SpyOutput(); - $this->exitter ->expects($this->never()) ->method('exit'); @@ -123,7 +123,7 @@ public function testNotifyWhenCoverageIsOk(): void minCoverageRules: MinCoverageRules::fromConfigFile('tests/Subscriber/Application/min-coverage-rules-success.php'), cleanUpCloverXml: false, exitter: $this->exitter, - consoleOutput: new ConsoleOutput($spyOutput), + consoleOutput: new ConsoleOutput($this->output, $this->resourceUsageFormatter), timer: $this->timer, ); @@ -143,13 +143,11 @@ public function testNotifyWhenCoverageIsOk(): void 0 )); - $this->assertMatchesTextSnapshot($spyOutput); + $this->assertMatchesTextSnapshot($this->output); } public function testNotifyWithOnlyTotal(): void { - $spyOutput = new SpyOutput(); - $this->exitter ->expects($this->never()) ->method('exit'); @@ -159,7 +157,7 @@ public function testNotifyWithOnlyTotal(): void minCoverageRules: MinCoverageRules::fromConfigFile('tests/Subscriber/Application/min-coverage-rules-total-only.php'), cleanUpCloverXml: false, exitter: $this->exitter, - consoleOutput: new ConsoleOutput($spyOutput), + consoleOutput: new ConsoleOutput($this->output, $this->resourceUsageFormatter), timer: $this->timer, ); @@ -179,13 +177,11 @@ public function testNotifyWithOnlyTotal(): void 0 )); - $this->assertMatchesTextSnapshot($spyOutput); + $this->assertMatchesTextSnapshot($this->output); } public function testNotifyWithoutTotal(): void { - $spyOutput = new SpyOutput(); - $this->exitter ->expects($this->never()) ->method('exit'); @@ -195,7 +191,7 @@ public function testNotifyWithoutTotal(): void minCoverageRules: MinCoverageRules::fromConfigFile('tests/Subscriber/Application/min-coverage-rules-without-total.php'), cleanUpCloverXml: false, exitter: $this->exitter, - consoleOutput: new ConsoleOutput($spyOutput), + consoleOutput: new ConsoleOutput($this->output, $this->resourceUsageFormatter), timer: $this->timer, ); @@ -215,13 +211,11 @@ public function testNotifyWithoutTotal(): void 0 )); - $this->assertMatchesTextSnapshot($spyOutput); + $this->assertMatchesTextSnapshot($this->output); } public function testNotifyWithRulesThatDoNotExit(): void { - $spyOutput = new SpyOutput(); - $this->exitter ->expects($this->never()) ->method('exit'); @@ -231,7 +225,7 @@ public function testNotifyWithRulesThatDoNotExit(): void minCoverageRules: MinCoverageRules::fromConfigFile('tests/Subscriber/Application/min-coverage-rules-no-exit.php'), cleanUpCloverXml: false, exitter: $this->exitter, - consoleOutput: new ConsoleOutput($spyOutput), + consoleOutput: new ConsoleOutput($this->output, $this->resourceUsageFormatter), timer: $this->timer, ); @@ -251,13 +245,11 @@ public function testNotifyWithRulesThatDoNotExit(): void 0 )); - $this->assertMatchesTextSnapshot($spyOutput); + $this->assertMatchesTextSnapshot($this->output); } public function testDivideByZero(): void { - $spyOutput = new SpyOutput(); - $this->exitter ->expects($this->never()) ->method('exit'); @@ -267,7 +259,7 @@ public function testDivideByZero(): void minCoverageRules: MinCoverageRules::fromInt(100, true), cleanUpCloverXml: false, exitter: $this->exitter, - consoleOutput: new ConsoleOutput($spyOutput), + consoleOutput: new ConsoleOutput($this->output, $this->resourceUsageFormatter), timer: $this->timer, ); @@ -287,13 +279,11 @@ public function testDivideByZero(): void 0 )); - $this->assertMatchesTextSnapshot($spyOutput); + $this->assertMatchesTextSnapshot($this->output); } public function testNotifyWithNonExistingCloverFile(): void { - $spyOutput = new SpyOutput(); - $this->exitter ->expects($this->never()) ->method('exit'); @@ -303,7 +293,7 @@ public function testNotifyWithNonExistingCloverFile(): void minCoverageRules: MinCoverageRules::fromConfigFile('tests/Subscriber/Application/min-coverage-rules-success.php'), cleanUpCloverXml: false, exitter: $this->exitter, - consoleOutput: new ConsoleOutput($spyOutput), + consoleOutput: new ConsoleOutput($this->output, $this->resourceUsageFormatter), timer: $this->timer, ); @@ -323,13 +313,11 @@ public function testNotifyWithNonExistingCloverFile(): void 0 )); - $this->assertEmpty((string) $spyOutput); + $this->assertEmpty((string) $this->output); } public function testNotifyWithInvalidCloverFile(): void { - $spyOutput = new SpyOutput(); - $this->exitter ->expects($this->never()) ->method('exit'); @@ -339,7 +327,7 @@ public function testNotifyWithInvalidCloverFile(): void minCoverageRules: MinCoverageRules::fromConfigFile('tests/Subscriber/Application/min-coverage-rules-success.php'), cleanUpCloverXml: false, exitter: $this->exitter, - consoleOutput: new ConsoleOutput($spyOutput), + consoleOutput: new ConsoleOutput($this->output, $this->resourceUsageFormatter), timer: $this->timer, ); @@ -367,8 +355,6 @@ public function testNotifyWithCleanUpCloverFile(): void { copy(dirname(__DIR__, 2).'/clover.xml', dirname(__DIR__, 2).'/clover-to-delete.xml'); - $spyOutput = new SpyOutput(); - $this->exitter ->expects($this->once()) ->method('exit'); @@ -378,7 +364,7 @@ public function testNotifyWithCleanUpCloverFile(): void minCoverageRules: MinCoverageRules::fromConfigFile('tests/Subscriber/Application/min-coverage-rules-with-failed-rule.php'), cleanUpCloverXml: true, exitter: $this->exitter, - consoleOutput: new ConsoleOutput($spyOutput), + consoleOutput: new ConsoleOutput($this->output, $this->resourceUsageFormatter), timer: $this->timer, ); @@ -403,8 +389,6 @@ public function testNotifyWithCleanUpCloverFile(): void public function testNotifyWithDuplicatePatterns(): void { - $spyOutput = new SpyOutput(); - $this->exitter ->expects($this->never()) ->method('exit'); @@ -417,15 +401,13 @@ public function testNotifyWithDuplicatePatterns(): void minCoverageRules: MinCoverageRules::fromConfigFile('tests/Subscriber/Application/min-coverage-rules-with-duplicates.php'), cleanUpCloverXml: false, exitter: $this->exitter, - consoleOutput: new ConsoleOutput($spyOutput), + consoleOutput: new ConsoleOutput($this->output, $this->resourceUsageFormatter), timer: $this->timer, ); } public function testNotifyWithInvalidRules(): void { - $spyOutput = new SpyOutput(); - $this->exitter ->expects($this->never()) ->method('exit'); @@ -438,15 +420,13 @@ public function testNotifyWithInvalidRules(): void minCoverageRules: MinCoverageRules::fromConfigFile('tests/Subscriber/Application/min-coverage-rules-invalid.php'), cleanUpCloverXml: false, exitter: $this->exitter, - consoleOutput: new ConsoleOutput($spyOutput), + consoleOutput: new ConsoleOutput($this->output, $this->resourceUsageFormatter), timer: $this->timer, ); } public function testNotifyWithInvalidRuleInstances(): void { - $spyOutput = new SpyOutput(); - $this->exitter ->expects($this->never()) ->method('exit'); @@ -459,7 +439,7 @@ public function testNotifyWithInvalidRuleInstances(): void minCoverageRules: MinCoverageRules::fromConfigFile('tests/Subscriber/Application/min-coverage-invalid-rule-instances.php'), cleanUpCloverXml: false, exitter: $this->exitter, - consoleOutput: new ConsoleOutput($spyOutput), + consoleOutput: new ConsoleOutput($this->output, $this->resourceUsageFormatter), timer: $this->timer, ); }