Skip to content

Commit a1aec59

Browse files
Merge pull request #9 from robiningelbrecht/output-execution-time
Output execution time
2 parents f0c6672 + 1c35b19 commit a1aec59

18 files changed

+296
-105
lines changed

phpunit.xml.dist

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,5 @@
1818
<include>
1919
<directory>src</directory>
2020
</include>
21-
<exclude>
22-
<file>src/Exitter.php</file>
23-
</exclude>
2421
</source>
2522
</phpunit>

src/ConsoleOutput.php

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44

55
use RobinIngelbrecht\PHPUnitCoverageTools\MinCoverage\MinCoverageResult;
66
use RobinIngelbrecht\PHPUnitCoverageTools\MinCoverage\ResultStatus;
7+
use RobinIngelbrecht\PHPUnitCoverageTools\Timer\ResourceUsageFormatter;
8+
use RobinIngelbrecht\PHPUnitCoverageTools\Timer\SystemResourceUsageFormatter;
9+
use SebastianBergmann\Timer\Duration;
710
use Symfony\Component\Console\Formatter\OutputFormatterStyle;
811
use Symfony\Component\Console\Helper\Table;
912
use Symfony\Component\Console\Helper\TableCell;
@@ -12,10 +15,11 @@
1215
use Symfony\Component\Console\Helper\TableStyle;
1316
use Symfony\Component\Console\Output\OutputInterface;
1417

15-
class ConsoleOutput
18+
final class ConsoleOutput
1619
{
1720
public function __construct(
1821
private readonly OutputInterface $output,
22+
private readonly ResourceUsageFormatter $resourceUsageFormatter,
1923
) {
2024
$this->output->setDecorated(true);
2125
$this->output->getFormatter()->setStyle(
@@ -36,10 +40,18 @@ public function __construct(
3640
);
3741
}
3842

43+
public static function create(): self
44+
{
45+
return new self(
46+
output: new \Symfony\Component\Console\Output\ConsoleOutput(),
47+
resourceUsageFormatter: SystemResourceUsageFormatter::create()
48+
);
49+
}
50+
3951
/**
4052
* @param \RobinIngelbrecht\PHPUnitCoverageTools\MinCoverage\MinCoverageResult[] $results
4153
*/
42-
public function print(array $results): void
54+
public function print(array $results, Duration $duration): void
4355
{
4456
$statusWeights = array_map(fn (MinCoverageResult $result) => $result->getStatus()->getWeight(), $results);
4557
$finalStatus = ResultStatus::fromWeight(max($statusWeights));
@@ -99,5 +111,6 @@ public function print(array $results): void
99111
],
100112
]);
101113
$table->render();
114+
$this->output->writeln($this->resourceUsageFormatter->resourceUsage($duration));
102115
}
103116
}

src/Exitter.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
namespace RobinIngelbrecht\PHPUnitCoverageTools;
44

5+
/**
6+
* @codeCoverageIgnore
7+
*/
58
class Exitter
69
{
710
public function exit(): void

src/Subscriber/Application/ApplicationFinishedSubscriber.php

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
use RobinIngelbrecht\PHPUnitCoverageTools\MinCoverage\MinCoverageRule;
1515
use RobinIngelbrecht\PHPUnitCoverageTools\MinCoverage\MinCoverageRules;
1616
use RobinIngelbrecht\PHPUnitCoverageTools\MinCoverage\ResultStatus;
17+
use RobinIngelbrecht\PHPUnitCoverageTools\Timer\SystemTimer;
18+
use RobinIngelbrecht\PHPUnitCoverageTools\Timer\Timer;
1719
use Symfony\Component\Console\Helper\FormatterHelper;
1820

1921
final class ApplicationFinishedSubscriber extends FormatterHelper implements FinishedSubscriber
@@ -24,11 +26,13 @@ public function __construct(
2426
private readonly bool $cleanUpCloverXml,
2527
private readonly Exitter $exitter,
2628
private readonly ConsoleOutput $consoleOutput,
29+
private readonly Timer $timer,
2730
) {
2831
}
2932

3033
public function notify(Finished $event): void
3134
{
35+
$this->timer->start();
3236
/** @var string $reflectionFileName */
3337
$reflectionFileName = (new \ReflectionClass(ClassLoader::class))->getFileName();
3438
$absolutePathToCloverXml = dirname($reflectionFileName, 3).'/'.$this->relativePathToCloverXml;
@@ -48,15 +52,21 @@ public function notify(Finished $event): void
4852
if ($this->minCoverageRules->hasTotalRule() && \XMLReader::ELEMENT == $reader->nodeType && 'metrics' == $reader->name && 2 === $reader->depth) {
4953
/** @var \SimpleXMLElement $node */
5054
$node = simplexml_load_string($reader->readOuterXml());
51-
$metricTotal = CoverageMetric::fromCloverXmlNode($node, MinCoverageRule::TOTAL);
55+
$metricTotal = CoverageMetric::fromCloverXmlNode(
56+
node: $node,
57+
forClass: MinCoverageRule::TOTAL
58+
);
5259
continue;
5360
}
5461
if ($this->minCoverageRules->hasOtherRulesThanTotalRule() && \XMLReader::ELEMENT == $reader->nodeType && 'class' == $reader->name && 3 === $reader->depth) {
5562
/** @var \SimpleXMLElement $node */
5663
$node = simplexml_load_string($reader->readInnerXml());
5764
/** @var string $className */
5865
$className = $reader->getAttribute('name');
59-
$metrics[] = CoverageMetric::fromCloverXmlNode($node, $className);
66+
$metrics[] = CoverageMetric::fromCloverXmlNode(
67+
node: $node,
68+
forClass: $className
69+
);
6070
}
6171
}
6272
$reader->close();
@@ -74,7 +84,11 @@ public function notify(Finished $event): void
7484
metrics: $metrics,
7585
metricTotal: $metricTotal,
7686
);
77-
$this->consoleOutput->print($results);
87+
88+
$this->consoleOutput->print(
89+
results: $results,
90+
duration: $this->timer->stop()
91+
);
7892

7993
$needsExit = !empty(array_filter(
8094
$results,
@@ -134,7 +148,8 @@ public static function fromConfigurationAndParameters(
134148
minCoverageRules: $rules,
135149
cleanUpCloverXml: $cleanUpCloverXml,
136150
exitter: new Exitter(),
137-
consoleOutput: new ConsoleOutput(new \Symfony\Component\Console\Output\ConsoleOutput()),
151+
consoleOutput: ConsoleOutput::create(),
152+
timer: SystemTimer::create(),
138153
);
139154
}
140155
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?php
2+
3+
namespace RobinIngelbrecht\PHPUnitCoverageTools\Timer;
4+
5+
use SebastianBergmann\Timer\Duration;
6+
7+
interface ResourceUsageFormatter
8+
{
9+
public function resourceUsage(Duration $duration): string;
10+
11+
public function resourceUsageSinceStartOfRequest(): string;
12+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php
2+
3+
namespace RobinIngelbrecht\PHPUnitCoverageTools\Timer;
4+
5+
use SebastianBergmann\Timer\Duration;
6+
use SebastianBergmann\Timer\ResourceUsageFormatter as PhpUnitResourceUsageFormatter;
7+
8+
final class SystemResourceUsageFormatter implements ResourceUsageFormatter
9+
{
10+
private function __construct(
11+
private readonly PhpUnitResourceUsageFormatter $resourceUsageFormatter
12+
) {
13+
}
14+
15+
public static function create(): self
16+
{
17+
return new self(new PhpUnitResourceUsageFormatter());
18+
}
19+
20+
/**
21+
* @codeCoverageIgnore
22+
*/
23+
public function resourceUsage(Duration $duration): string
24+
{
25+
return $this->resourceUsageFormatter->resourceUsage($duration);
26+
}
27+
28+
/**
29+
* @codeCoverageIgnore
30+
*/
31+
public function resourceUsageSinceStartOfRequest(): string
32+
{
33+
return $this->resourceUsageFormatter->resourceUsageSinceStartOfRequest();
34+
}
35+
}

src/Timer/SystemTimer.php

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php
2+
3+
namespace RobinIngelbrecht\PHPUnitCoverageTools\Timer;
4+
5+
use SebastianBergmann\Timer\Duration;
6+
use SebastianBergmann\Timer\Timer as PhpUnitTimer;
7+
8+
final class SystemTimer implements Timer
9+
{
10+
private function __construct(
11+
private readonly PhpUnitTimer $timer,
12+
) {
13+
}
14+
15+
public static function create(): self
16+
{
17+
return new self(new PhpUnitTimer());
18+
}
19+
20+
/**
21+
* @codeCoverageIgnore
22+
*/
23+
public function start(): void
24+
{
25+
$this->timer->start();
26+
}
27+
28+
/**
29+
* @codeCoverageIgnore
30+
*/
31+
public function stop(): Duration
32+
{
33+
return $this->timer->stop();
34+
}
35+
}

src/Timer/Timer.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?php
2+
3+
namespace RobinIngelbrecht\PHPUnitCoverageTools\Timer;
4+
5+
use SebastianBergmann\Timer\Duration;
6+
7+
interface Timer
8+
{
9+
public function start(): void;
10+
11+
public function stop(): Duration;
12+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<?php
2+
3+
namespace Tests;
4+
5+
use RobinIngelbrecht\PHPUnitCoverageTools\Timer\ResourceUsageFormatter;
6+
use SebastianBergmann\Timer\Duration;
7+
8+
final class FixedResourceUsageFormatter implements ResourceUsageFormatter
9+
{
10+
private function __construct(
11+
private readonly float $usageInMb
12+
) {
13+
}
14+
15+
public static function withUsageInMb(float $usageInMb): self
16+
{
17+
return new self($usageInMb);
18+
}
19+
20+
public function resourceUsage(Duration $duration): string
21+
{
22+
return sprintf(
23+
'Time: %s, Memory: %s MB',
24+
$duration->asString(),
25+
number_format($this->usageInMb, 2, '.', ''),
26+
);
27+
}
28+
29+
public function resourceUsageSinceStartOfRequest(): string
30+
{
31+
return sprintf(
32+
'Time: 00:00.350, Memory: %s MB',
33+
number_format($this->usageInMb, 2, '.', ''),
34+
);
35+
}
36+
}

tests/PausedTimer.php

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php
2+
3+
namespace Tests;
4+
5+
use RobinIngelbrecht\PHPUnitCoverageTools\Timer\Timer;
6+
use SebastianBergmann\Timer\Duration;
7+
8+
final class PausedTimer implements Timer
9+
{
10+
private function __construct(
11+
private readonly Duration $duration
12+
) {
13+
}
14+
15+
public static function withDuration(Duration $duration): self
16+
{
17+
return new self($duration);
18+
}
19+
20+
public function start(): void
21+
{
22+
}
23+
24+
public function stop(): Duration
25+
{
26+
return $this->duration;
27+
}
28+
}

0 commit comments

Comments
 (0)