I don't have a direct example, but I would approach this in the following way. The code is untested, and will likely require changes to work, take this as a starting point
In any case, you want to do the following things:
- Collect code coverage data for each request, and store that to a file
- Aggregate the code coverage data for each of these runs, and merge them
Collecting Code Coverage for Each Request
Traditionally code coverage is generated for unit tests, with PHPUnit. PHPUnit uses a separate library, PHP Code Coverage, to collect, merge and generate reports for the per-test collected coverage. You can use this library stand alone.
To collect the data, I would do composer require phpunit/php-code-coverage and then create an auto_prepend file, with something like the following in it:
<?php
require 'vendor/autoload.php';
use SebastianBergmann\CodeCoverage\Filter;
use SebastianBergmann\CodeCoverage\Driver\Selector;
use SebastianBergmann\CodeCoverage\CodeCoverage;
use SebastianBergmann\CodeCoverage\Report\Html\Facade as HtmlReport;
$filter = new Filter;
$filter->includeDirectory('/path/to/directory');
$coverage = new CodeCoverage(
(new Selector)->forLineCoverage($filter),
$filter
);
$coverage->start($_SERVER['REQUEST_URI']);
function save_coverage()
{
global $coverage;
$coverage->stop();
$data = $coverage->getData();
file_put_contents('/tmp/path/crawler/' . bin2hex(random_bytes(16)), serialize($data) . '.serialized', $data->get );
}
register_shutdown_function('save_coverage');
?>
(I copied most of that from the introduction in the php-code-coverage README.md)
You need to configure this prepend_file with php.ini: auto_prepend_file.
When you now crawl through your web site, you should get a file with code coverage for each request into /tmp/path/crawler/, but make sure that directory exists first.
Merging Code Coverage
For this step, you need to write a script that load each of the generate files (look at glob()), and merge them together.
PHP Code Coverage has a method for this too. It would look something like:
<?php
require 'vendor/autoload.php';
use SebastianBergmann\CodeCoverage\Filter;
use SebastianBergmann\CodeCoverage\Driver\Selector;
use SebastianBergmann\CodeCoverage\CodeCoverage;
use SebastianBergmann\CodeCoverage\Report\Html\Facade as HtmlReport;
$filter = new Filter;
$filter->includeDirectory('/path/to/directory');
$coverage = new CodeCoverage(
(new Selector)->forLineCoverage($filter),
$filter
);
foreach ( glob('/tmp/path/crawler/*.serialize') as $file)
{
$data = unserialize( file_get_contents( $file ) );
$fileCoverage = new CodeCoverage(
(new Selector)->forLineCoverage($filter),
$filter
);
$fileCoverage->setData( $data );
$coverage->merge( $fileCoverage );
}
/* now generate the report, as per the README.md again */
(new HtmlReport)->process($coverage, '/tmp/code-coverage-report');
?>
If I find some time, I will do a video on this.