Skip to content

Instantly share code, notes, and snippets.

@bodik
Created June 8, 2020 12:56
Show Gist options
  • Save bodik/6fd7b64c64730d7fed508d827a39e8a5 to your computer and use it in GitHub Desktop.
Save bodik/6fd7b64c64730d7fed508d827a39e8a5 to your computer and use it in GitHub Desktop.
coverage-checker2.php improved version
<?php
# coverage-checker2.php, improved version
# https://ocramius.github.io/blog/automated-code-coverage-check-for-github-pull-requests-with-travis/
# https://stackoverflow.com/questions/13592547/how-to-group-numbers-in-ranges-using-php
function format_sequence($numbers) {
$groups = [];
$result = [];
sort($numbers);
for($i = 0; $i < count($numbers); $i++) {
if($i > 0 && ($numbers[$i - 1] == $numbers[$i] - 1))
array_push($groups[count($groups) - 1], $numbers[$i]);
else // First value or no match, create a new group
array_push($groups, array($numbers[$i]));
}
foreach($groups as $group) {
if(count($group) == 1) // Single value
array_push($result, $group[0]);
else // Range of values, minimum in [0], maximum in [count($group) - 1]
array_push($result, "${group[0]}-${group[count($group)-1]}");
}
return implode(",", $result);
}
function overall_coverage($xml) {
$metrics = $xml->xpath('//metrics');
$totalElements = 0;
$checkedElements = 0;
foreach ($metrics as $metric) {
$totalElements += (int) $metric['elements'];
$checkedElements += (int) $metric['coveredelements'];
}
return ($checkedElements / $totalElements) * 100;
}
function file_coverage($file_elem) {
$name = (string) $file_elem['name'];
$metrics = $file_elem->xpath('./metrics')[0];
# elements = conditionals + statements
$elements = (int) $metrics['elements'];
$miss = (int) $metrics['elements'] - (int) $metrics['coveredelements'];
if (($metrics['elements'] == 0) && ($metrics['coveredelements'] == 0)) {
$coverage = 100;
} elseif (($metrics['elements'] == 0) || ($metrics['coveredelements'] == 0)) {
$coverage = 0;
} else {
$coverage = ($metrics['coveredelements'] / $metrics['elements']) * 100;
}
$missed_lines = array_map(function($item) {return (int) $item["num"];}, $file_elem->xpath('./line[@count="0"]'));
$missing = format_sequence($missed_lines);
return [$name, $elements, $miss, $coverage, $missing];
}
function main($input_file, $percentage) {
if (!file_exists($input_file)) {
throw new InvalidArgumentException('Invalid input file provided');
}
if (($percentage < 0) || ($percentage > 100)) {
throw new InvalidArgumentException('Invalid pecrentage');
}
$xmldata = new SimpleXMLElement(file_get_contents($input_file));
$covdata = array_map('file_coverage',$xmldata->xpath('//file'));
$filenames = array_map(function($item){return $item[0];}, $covdata);
$longest_filename = max(array_map('strlen', $filenames));
$coverage = overall_coverage($xmldata);
$fmt = "%-${longest_filename}s %5s %5s %5s%% %s\n";
vprintf($fmt, ['Filename', 'Stmts', 'Miss', 'Cover', 'Missing']);
vprintf("%s\n", str_repeat('-', $longest_filename+34));
foreach ($covdata as $item) {
vprintf($fmt, $item);
}
vprintf("%s\n", str_repeat('-', $longest_filename+34));
vprintf($fmt, ['TOTAL', '', '', sprintf("%.2f", $coverage), '']);
if ($coverage < $percentage) {
return 1;
}
return 0;
}
main($argv[1], (int) $argv[2]);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment