Skip to content

Commit 2f95d1f

Browse files
authored
Implement local history
1 parent ea7f06d commit 2f95d1f

16 files changed

+366
-44
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,4 @@ vendor
1111

1212
# project
1313
build
14+
.history

composer.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88
"phpunit/phpunit": "^9"
99
},
1010
"require-dev": {
11-
"squizlabs/php_codesniffer": "^3.5"
11+
"squizlabs/php_codesniffer": "^3.5",
12+
"perchten/rmrdir": "^1.0"
1213
},
1314
"scripts": {
1415
"post-install-cmd": [

composer.lock

Lines changed: 43 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

phpunit.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
<testsuites>
1212
<testsuite name="Integration Tests">
1313
<file>./tests/integration/IntegrationTest.php</file>
14+
<file>./tests/integration/LocalHistoryTest.php</file>
1415
</testsuite>
1516
</testsuites>
1617
</phpunit>

src/Config.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,14 @@ public function getFormat(): string
137137
return getenv('FORMAT') ?: 'text';
138138
}
139139

140+
/**
141+
* Returns whether the local history is enabled.
142+
*/
143+
public function isLocalHistoryEnabled(): bool
144+
{
145+
return $this->config['localHistory'] ?? false;
146+
}
147+
140148
/**
141149
* Merge two configuration arrays.
142150
*/

src/Printer.php

Lines changed: 34 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -133,25 +133,25 @@ protected function printFooter(TestResult $result): void
133133
$missingExtraTests[] = $groupName . ' > ' . $testName;
134134
}
135135

136-
if ($this->json) {
137-
$groupJson['tests'][] = [
138-
'name' => $testName,
139-
'points' => $result['main']['status'] === true ? $result['main']['points'] : 0,
140-
'maxPoints' => $result['main']['points'],
141-
'successful' => $result['main']['status'] === true,
142-
'required' => $result['main']['required'] === true,
143-
'manualCheck' => $result['main']['status'] === true && isset($result['extra']) &&
144-
$result['extra']['status'] === false,
145-
];
146-
} else {
136+
$groupJson['tests'][] = [
137+
'name' => $testName,
138+
'points' => $result['main']['status'] === true ? $result['main']['points'] : 0,
139+
'maxPoints' => $result['main']['points'],
140+
'successful' => $result['main']['status'] === true,
141+
'required' => $result['main']['required'] === true,
142+
'manualCheck' => $result['main']['status'] === true && isset($result['extra']) &&
143+
$result['extra']['status'] === false,
144+
];
145+
146+
if (!$this->json) {
147147
if ($result['main']['status'] === false) {
148148
$resultSymbol = '';
149149
$resultColor = 'red';
150150
} elseif (
151151
$result['main']['status'] === true && (
152-
!$this->hasExtraTests ||
153-
!isset($result['extra']['status']) ||
154-
$result['extra']['status'] === true
152+
!$this->hasExtraTests ||
153+
!isset($result['extra']['status']) ||
154+
$result['extra']['status'] === true
155155
)
156156
) {
157157
$resultSymbol = '';
@@ -177,7 +177,7 @@ protected function printFooter(TestResult $result): void
177177
}
178178
}
179179

180-
if ($this->json && $hasMainTests) {
180+
if ($hasMainTests) {
181181
$json['testResults'][] = $groupJson;
182182
}
183183
}
@@ -232,6 +232,10 @@ protected function printFooter(TestResult $result): void
232232
} else {
233233
$this->write("\n");
234234
}
235+
236+
if (Config::getInstance()->isLocalHistoryEnabled()) {
237+
$this->saveHistory($json);
238+
}
235239
}
236240

237241
/**
@@ -409,4 +413,19 @@ private function printTestWarnings(string $warning, array $tests): string
409413

410414
return $warning . "\n - " . implode("\n - ", $tests);
411415
}
416+
417+
/**
418+
* Saves the test result to the local history
419+
*/
420+
private function saveHistory(array $result): void
421+
{
422+
$historyDir = Config::getProjectRoot() . DIRECTORY_SEPARATOR . '.history';
423+
$historyFile = $historyDir . DIRECTORY_SEPARATOR . uniqid() . '.json';
424+
425+
if (!file_exists($historyDir)) {
426+
mkdir($historyDir);
427+
}
428+
429+
file_put_contents($historyFile, json_encode(array_merge(['time' => time()], $result), JSON_PRETTY_PRINT));
430+
}
412431
}

tests/ComposerHelpers.php

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?php
2+
3+
namespace Skills17\PHPUnit\Test;
4+
5+
trait ComposerHelpers
6+
{
7+
private function runComposerCommand(string $integrationTest, string $command): string
8+
{
9+
$dir = __DIR__ . DIRECTORY_SEPARATOR . 'integration' . DIRECTORY_SEPARATOR . $integrationTest;
10+
return shell_exec('composer --working-dir=' . $dir . ' ' . $command . ' 2> /dev/null');
11+
}
12+
13+
private function standardizeOutput(string $output): string
14+
{
15+
$result = preg_replace('/Time: \d{2}:\d{2}\.\d{3}, Memory: \d+\.\d+ [^\n]+\n/s', '', $output);
16+
$result = preg_replace('/\n[^\n]+(\/tests\/integration\/[a-zA-Z0-9_.\/-]+.php:\d+\n)/s', '$1', $result);
17+
$result = preg_replace('/PHPUnit \d+\.\d+\.\d+ by/s', 'PHPUnit * by', $result);
18+
19+
return trim($result);
20+
}
21+
22+
private function assertComposerCommandOutput(string $integrationTest, string $command, string $expectedFile)
23+
{
24+
$expectedOutputPath = __DIR__ . DIRECTORY_SEPARATOR . 'integration' . DIRECTORY_SEPARATOR . $integrationTest .
25+
DIRECTORY_SEPARATOR . $expectedFile;
26+
$this->assertTrue(file_exists($expectedOutputPath));
27+
$expectedOutput = file_get_contents($expectedOutputPath);
28+
29+
$actualOutput = $this->runComposerCommand($integrationTest, $command);
30+
31+
$this->assertEquals($this->standardizeOutput($expectedOutput), $this->standardizeOutput($actualOutput));
32+
}
33+
}

tests/integration/IntegrationTest.php

Lines changed: 4 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
<?php
22

3-
namespace Skills17\PHPUnit\Test;
3+
namespace Skills17\PHPUnit\Test\Integration;
44

55
use DirectoryIterator;
66
use PHPUnit\Framework\TestCase;
7+
use Skills17\PHPUnit\Test\ComposerHelpers;
78

89
class IntegrationTest extends TestCase
910
{
11+
use ComposerHelpers;
12+
1013
/**
1114
* @dataProvider integrationProvider
1215
*/
@@ -29,30 +32,4 @@ public function integrationProvider(): array
2932

3033
return $integrationTests;
3134
}
32-
33-
private function runComposerCommand(string $integrationTest, string $command): string
34-
{
35-
$dir = __DIR__ . DIRECTORY_SEPARATOR . $integrationTest;
36-
return shell_exec('composer --working-dir=' . $dir . ' ' . $command . ' 2> /dev/null');
37-
}
38-
39-
private function assertComposerCommandOutput(string $integrationTest, string $command, string $expectedFile)
40-
{
41-
$expectedOutputPath = __DIR__ . DIRECTORY_SEPARATOR . $integrationTest . DIRECTORY_SEPARATOR . $expectedFile;
42-
$this->assertTrue(file_exists($expectedOutputPath));
43-
$expectedOutput = file_get_contents($expectedOutputPath);
44-
45-
$actualOutput = $this->runComposerCommand($integrationTest, $command);
46-
47-
$this->assertEquals($this->standardizeOutput($expectedOutput), $this->standardizeOutput($actualOutput));
48-
}
49-
50-
private function standardizeOutput(string $output): string
51-
{
52-
$result = preg_replace('/Time: \d{2}:\d{2}\.\d{3}, Memory: \d+\.\d+ [^\n]+\n/s', '', $output);
53-
$result = preg_replace('/\n[^\n]+(\/tests\/integration\/[a-zA-Z0-9_.\/-]+.php:\d+\n)/s', '$1', $result);
54-
$result = preg_replace('/PHPUnit \d+\.\d+\.\d+ by/s', 'PHPUnit * by', $result);
55-
56-
return trim($result);
57-
}
5835
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<?php
2+
3+
namespace Skills17\PHPUnit\Test\Integration;
4+
5+
use PHPUnit\Framework\TestCase;
6+
use Skills17\PHPUnit\Test\ComposerHelpers;
7+
8+
class LocalHistoryTest extends TestCase
9+
{
10+
use ComposerHelpers;
11+
12+
private $historyDir = __DIR__ . DIRECTORY_SEPARATOR . 'local-history' . DIRECTORY_SEPARATOR . '.history';
13+
14+
public function setUp(): void
15+
{
16+
if (file_exists($this->historyDir)) {
17+
rmrdir($this->historyDir);
18+
}
19+
}
20+
21+
public function testLocalHistory(): void
22+
{
23+
$this->assertFalse(file_exists($this->historyDir));
24+
$this->runComposerCommand('local-history', 'test');
25+
$this->runComposerCommand('local-history', 'test:json');
26+
$this->assertTrue(file_exists($this->historyDir));
27+
28+
$history = array_filter(scandir($this->historyDir), function ($name) {
29+
return $name !== '.' && $name !== '..';
30+
});
31+
32+
$this->assertEquals(2, count($history));
33+
34+
foreach ($history as $file) {
35+
$json = json_decode(file_get_contents($this->historyDir . DIRECTORY_SEPARATOR . $file));
36+
$this->assertIsNumeric($json->time);
37+
$this->assertIsArray($json->testResults);
38+
}
39+
}
40+
41+
public function testLocalHistoryDisabledByDefault(): void
42+
{
43+
$historyPath = __DIR__ . DIRECTORY_SEPARATOR . 'config-minimal' . DIRECTORY_SEPARATOR . '.history';
44+
45+
$this->runComposerCommand('config-minimal', 'test');
46+
$this->assertFalse(file_exists($historyPath));
47+
}
48+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"name": "skills17/phpunit-helpers-integration-local-history",
3+
"description": "Integration tests for skills17/phpunit-helpers",
4+
"license": "MIT",
5+
"scripts": {
6+
"test": "../../../vendor/bin/phpunit",
7+
"test:dump": "composer test > expected.txt",
8+
"test:json": "FORMAT=json ../../../vendor/bin/phpunit | tail -n +3",
9+
"test:json:dump": "composer test:json > expected.json"
10+
},
11+
"authors": [
12+
{
13+
"name": "Cyril Wanner",
14+
"email": "[email protected]"
15+
}
16+
]
17+
}

tests/integration/local-history/composer.lock

Lines changed: 18 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"localHistory": true,
3+
"groups": [
4+
{
5+
"match": "A.+"
6+
},
7+
{
8+
"match": "B.+"
9+
},
10+
{
11+
"match": "C.+"
12+
}
13+
]
14+
}

0 commit comments

Comments
 (0)