Search code examples
phpseleniumxdebug

Measure code coverage using Xdebug when crawls web application


I build my crawler based on ChromeDriver Selenium , and I want to measure the code coverage of the web application when my automated crawler crawls the application.

So, my question is how I do that using Xdebug (I'm newer on it). I installed Xdebug on my PHP, but I didn't know how to start? Can anyone have an idea to give me steps for that because I didn't find any resource that help me.


Solution

  • 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:

    1. Collect code coverage data for each request, and store that to a file
    2. 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.