Skip to content

Commit 85512e9

Browse files
Some improvements
- Don't use the shutdown function by default - Don't use the coverage ID in the filename - Create the coverage directory if it doesn't exist
1 parent 8bca673 commit 85512e9

File tree

5 files changed

+91
-34
lines changed

5 files changed

+91
-34
lines changed

README.md

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,21 +12,21 @@ composer require matthiasnoback/live-code-coverage
1212

1313
## Collecting code coverage data
1414

15-
At the top of your front controller (e.g. `index.php`), add the following:
15+
In your front controller (e.g. `index.php`), add the following:
1616

1717
```php
1818
<?php
1919

20-
require __DIR__ . '/../vendor/autoload.php';
21-
2220
use LiveCodeCoverage\LiveCodeCoverage;
2321

24-
LiveCodeCoverage::bootstrap(
25-
__DIR__ . '/../coverage',
22+
$liveCodeCoverage = LiveCodeCoverage::bootstrap(
23+
__DIR__ . '/../var/coverage',
2624
__DIR__ . '/../phpunit.xml.dist'
2725
);
2826

2927
// Run your web application now
28+
29+
$liveCodeCoverage->stopAndSave();
3030
```
3131

3232
- The first argument is the directory where all the collected coverage data will be stored (`*.cov` files). This directory should already exist and be writable.
@@ -47,12 +47,23 @@ Any configuration directive that's [available in PHPUnit](https://phpunit.de/man
4747

4848
If you don't provide a PHPUnit configuration file, no filters will be applied, so you will get a coverage report for all the code in your project, including vendor and test code if applicable.
4949

50+
If your application is a legacy application which `exit()`s or `die()`s before execution reaches the end of your front controller, the bootstrap should be slightly different:
51+
52+
```php
53+
$liveCodeCoverage = LiveCodeCoverage::bootstrap(
54+
// ...
55+
);
56+
$liveCodeCoverage->stopAndSaveOnExit();
57+
58+
// Run your web application now
59+
```
60+
5061
## Generating code coverage reports (HTML, Clover, etc.)
5162

5263
To merge all the coverage data and generate a report for it, install Sebastian Bergmann's [`phpcov` tool](https://github.com/sebastianbergmann/phpcov). Run it like this (or in any other way you like):
5364

5465
```bash
55-
phpcov merge --html=./coverage/html ./coverage
66+
phpcov merge --html=./coverage/html ./var/coverage
5667
```
5768

5869
## Downsides

src/LiveCodeCoverage/LiveCodeCoverage.php

Lines changed: 14 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,14 @@ final class LiveCodeCoverage
2222
*/
2323
private $storageDirectory;
2424

25-
private function __construct(CodeCoverage $codeCoverage, $storageDirectory, $coverage_id)
25+
private function __construct(CodeCoverage $codeCoverage, $storageDirectory, $coverageId)
2626
{
27-
Assert::regex($coverage_id, '/^[\w\-]+$/');
2827
$this->codeCoverage = $codeCoverage;
29-
$this->coverageId = $coverage_id;
30-
Assert::directory($storageDirectory);
31-
Assert::writable($storageDirectory);
28+
$this->coverageId = $coverageId;
3229
$this->storageDirectory = $storageDirectory;
3330
}
3431

35-
public static function bootstrap($storageDirectory, $phpunitConfigFilePath = null, $coverage_id = 'live-coverage')
32+
public static function bootstrap($storageDirectory, $phpunitConfigFilePath = null, $coverageId = 'live-coverage')
3633
{
3734
if ($phpunitConfigFilePath !== null) {
3835
Assert::file($phpunitConfigFilePath);
@@ -41,33 +38,32 @@ public static function bootstrap($storageDirectory, $phpunitConfigFilePath = nul
4138
$codeCoverage = CodeCoverageFactory::createDefault();
4239
}
4340

44-
$liveCodeCoverage = new self($codeCoverage, $storageDirectory, $coverage_id);
41+
$liveCodeCoverage = new self($codeCoverage, $storageDirectory, $coverageId);
4542

4643
$liveCodeCoverage->start();
47-
register_shutdown_function([$liveCodeCoverage, 'stopAndSave']);
44+
45+
return $liveCodeCoverage;
4846
}
4947

5048
private function start()
5149
{
5250
$this->codeCoverage->start($this->coverageId);
5351
}
5452

53+
public function stopAndSaveOnExit()
54+
{
55+
register_shutdown_function([$this, 'stopAndSave']);
56+
}
57+
5558
public function stopAndSave()
5659
{
5760
$this->codeCoverage->stop();
5861

59-
$cov = '<?php return unserialize(' . var_export(serialize($this->codeCoverage), true) . ');';
60-
file_put_contents($this->generateCovFileName(), $cov);
62+
Storage::storeCodeCoverage($this->codeCoverage, $this->storageDirectory, $this->covFileName());
6163
}
6264

63-
private function generateCovFileName()
65+
private function covFileName()
6466
{
65-
$fileNameParts = [
66-
$this->coverageId,
67-
date('YmdHis'),
68-
uniqid('', true)
69-
];
70-
71-
return $this->storageDirectory . '/' . implode('-', $fileNameParts) . '.cov';
67+
return uniqid(date('YmdHis'), true);
7268
}
7369
}

src/LiveCodeCoverage/Storage.php

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
<?php
2+
3+
namespace LiveCodeCoverage;
4+
5+
use DirectoryIterator;
6+
use SebastianBergmann\CodeCoverage\CodeCoverage;
7+
use Webmozart\Assert\Assert;
8+
9+
final class Storage
10+
{
11+
/**
12+
* @param CodeCoverage $coverage
13+
* @param string $storageDirectory
14+
* @param $name
15+
* @return void
16+
* @throws \RuntimeException
17+
*/
18+
public static function storeCodeCoverage(CodeCoverage $coverage, $storageDirectory, $name)
19+
{
20+
Assert::string($storageDirectory);
21+
22+
if (!is_dir($storageDirectory)) {
23+
if (!mkdir($storageDirectory, 0777, true) && !is_dir($storageDirectory)) {
24+
throw new \RuntimeException(sprintf('Could not create directory "%s"', $storageDirectory));
25+
}
26+
}
27+
28+
$cov = '<?php return unserialize(' . var_export(serialize($coverage), true) . ');';
29+
$filePath = $storageDirectory . '/' . $name . '.cov';
30+
file_put_contents($filePath, $cov);
31+
}
32+
33+
/**
34+
* @param string $storageDirectory
35+
* @return CodeCoverage
36+
*/
37+
public static function loadFromDirectory($storageDirectory)
38+
{
39+
$coverage = new CodeCoverage();
40+
41+
if (!is_dir($storageDirectory)) {
42+
return $coverage;
43+
}
44+
45+
foreach (new DirectoryIterator($storageDirectory) as $file) {
46+
if ($file->isDot()) {
47+
continue;
48+
}
49+
50+
$partialCodeCoverage = include $file->getPathname();
51+
Assert::isInstanceOf($partialCodeCoverage, CodeCoverage::class);
52+
53+
$coverage->merge($partialCodeCoverage);
54+
}
55+
56+
return $coverage;
57+
}
58+
}

test/functional/LiveCodeCoverageTest.php

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -39,19 +39,10 @@ public function it_generates_cov_files_with_serialized_CodeCoverage_objects()
3939

4040
foreach ($finder as $covFile) {
4141
$filePath = (string)$covFile;
42-
$this->assertFileNameStartsWithExpectedPrefix($filePath);
4342
$this->assertIncludedFileReturnsCodeCoverageObject($filePath);
4443
}
4544
}
4645

47-
/**
48-
* @param $filePath
49-
*/
50-
private function assertFileNameStartsWithExpectedPrefix($filePath)
51-
{
52-
$this->assertRegExp('/^live-coverage/', basename($filePath));
53-
}
54-
5546
/**
5647
* @param $filePath
5748
*/

test/functional/prepend.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@
22

33
use LiveCodeCoverage\LiveCodeCoverage;
44

5-
LiveCodeCoverage::bootstrap(__DIR__ . '/coverage', __DIR__ . '/phpunit.xml.dist');
5+
$liveCodeCoverage = LiveCodeCoverage::bootstrap(__DIR__ . '/coverage', __DIR__ . '/phpunit.xml.dist');
6+
$liveCodeCoverage->stopAndSaveOnExit();

0 commit comments

Comments
 (0)