5

I have several clover.xml reports of different extensions of a projects. I want to combine them into one clover.xml and then create it into a clover html. But i see no way with the phpunit classes PHP_CodeCoverage, PHP_CodeCoverage_Report_HTML, PHP_CodeCoverage_Report_Clover.

None of these classes accept an existing clover.xml. I thought I might be able to work with the methods append and merge of PHP_CodeCoverage. But that does not accept files.

Prof. Falken
  • 24,226
  • 19
  • 100
  • 173
user1791139
  • 606
  • 1
  • 11
  • 27
  • Same problem here. It's a matrix build. Each clover.xml has certain skips. While the merged clover.xml shouldn't have them. PHPUnit does not provide a coverage merging util. – Jens A. Koch Nov 10 '12 at 10:51
  • I guess it cannot be done. As PHPUnit is using xdebug to find out which lines have been called and which hasn't. To just merge the line coverage seems to be possible. But if you look into the xml file, you'll see that there are other metrics, like statement coverage. For that you need to tokenize the source to decide if a statement (function) has been fully covered or not. – jkrnak Jan 22 '14 at 17:42

3 Answers3

0

If you are running jenkins or similar include a php script in your Ant build file to merge the files using SimpleXML

An example is here http://kuttler.eu/post/merging-and-splitting-xml-files-with-simplexml/

Then in your post build actions jenkins will use the clover.xml to generate your code coverage

enter image description here

Josh Woodcock
  • 2,683
  • 1
  • 22
  • 29
  • But how exactly to merge different coverage XML? I mean based on which XML node? My XML have (roughly) the following structure: ... ... – Obaid Maroof Mar 21 '14 at 13:32
  • Sorry, but I couldn't find a way to format/structure the XML in the comments section. – Obaid Maroof Mar 21 '14 at 13:35
  • Here's an example of how to merge 2 xml reports. Though this is for merging phpcs.xml files the concept is the same.http://beagile.biz/merge-2-php-code-sniffer-clover-xml-reports/ – Josh Woodcock Jul 20 '14 at 15:17
0

As jkrnak commented above you cannot simply merge the XML files as there are computed values such as lines covered etc.. that are computed at output time. You need to "merge" while still working with native PHP code. In my case I wanted to capture the coverage of a series of web service calls executed by newman. To do this I set a flag at the beginning of execution which persists across invocations (using a cache) and then also save the PHP_CodeCoverage object in the cache as well. My implementation (in Laravel) looks something like this:

if ( isset($_GET['initCoverage']) )
{
    Cache::put( 'recordCoverage', true, 1440 );
}

if ( Cache::has('recordCoverage') )
{
    if ( Cache::has('coverage') )
    {
        $coverage = Cache::get('coverage');
    }
    else
    {
        $filter = new PHP_CodeCoverage_Filter;
        $filter->addDirectoryToBlacklist( base_path() . '/vendor' );

        $coverage = new PHP_CodeCoverage( null, $filter );
    }

    $coverage->start( Request::method() . " " . Request::path() );

    if ( isset($_GET['dumpCoverage']) )
    {
        if ( Cache::has('coverage') ) 
        {
            // Prevent timeout as writing coverage reports takes a long time
            set_time_limit( 0 );

            $coverage = Cache::get( 'coverage' );
            $writer = new PHP_CodeCoverage_Report_Clover;
            $writer->process($coverage, 'results/coverage/clover.xml');
        }

        Cache::forget('recordCoverage');
        Cache::forget('coverage');
    }
    else
    {
        register_shutdown_function( function($coverage) 
        {
            $coverage->stop();

            Cache::put( 'coverage', $coverage, 1440);
        }, $coverage);
    }
}

This captures the series of tests in a single coverage object which is then output when I make a call with the "dumpCoverage" flag.

darrylkuhn
  • 1,318
  • 1
  • 9
  • 9
0

Years later this issue is still partly unsolved. There is a project by SB that can merge clover files, but it requires php 5.6.

None of the answers above work sufficiently well. Here is a gist of a merge thrown together. Constructive critisism welcome.

Usage:

php clover-merge.php -o merged.xml -f clover-phpunit.xml -f clover-phpspec.xml

Posting it here for posterity too:

<?php
$options = getopt("f:o:");
if (! isset($options['f'])) {
    echo "Files have to be specified with -f\n";
    exit(1);
}
if (! isset($options['o'])) {
    echo "Output has to be specified with -o\n";
    exit(1);
}

$files = $options['f'];
if (! is_array($files)) {
    $files = array($files);
}
$output = $options['o'];

$buffer = '';
foreach ($files as $file) {
    if (! file_exists($file)) {
        echo "File '$file' doesn't exist\n";
        exit(2);
    }
    $report = simplexml_load_file($file);
    $buffer .= $report->project->asXML();
}

$fh = fopen($output ,'w');
if (! $fh) {
    echo "Cannot open '$output' for writing\n";
    exit(2);
}
fwrite($fh, sprintf('<?xml version="1.0" encoding="UTF-8"?><coverage>%s</coverage>', $buffer));
fclose($fh);
Yarek T
  • 9,715
  • 2
  • 28
  • 38