phpunit — как генерировать отчеты о покрытии кода PHP из вывода xdebug

Я пытаюсь сгенерировать отчет о покрытии кода HTML для работающего приложения PHP. Моя цель — профилировать приложение с помощью XDebug, пока я выполняю свои функциональные тесты, чтобы определить охват кода моего функционального набора тестов.

Я могу измерить покрытие кода для своих модульных тестов с помощью phpunit (который использует API покрытия php-code для индивидуального профилирования каждого модульного теста, а затем объединяет его в отчет о покрытии кода). И поскольку эти инструменты построены на основе xdebug, я надеюсь, что есть способ взять выходной файл из профилировщика XDebug и сгенерировать отчет HTML.

Вот что у меня так далеко:

Я могу создать файл cachegrind.out, добавив следующую конфигурацию в php.ini:

xdebug.profiler_enable_trigger=1
xdebug.profiler_output_dir=/var/log/xdebug_profiler
xdebug.profiler_output_name=cachegrind.out
xdebug.profiler_append=1
xdebug.coverage_enable=1

Затем я выполняю свои функциональные тесты с расширением XDebug Helper Chrome в режиме «ПРОФИЛЬ». Это добавляет XDEBUG_PROFILE в поле cookie HTTP-запросов, что, в свою очередь, запускает профилировщик в приложении PHP. (В качестве альтернативы вы можете просто включить профилировщик для всех запросов с xdebug.profiler_enable = 1)

У меня проблема с преобразованием выходного файла (cachegrind.out) в тот же HTML-отчет, который предоставляется phpunit. Я могу вывести профилировщик с помощью kcachegrind, но у этого приложения нет способа экспортировать отчет о покрытии кода, не говоря уже об указании включенных / исключенных файлов.

Я также изучил инструмент командной строки phpcov, но, хотя он поддерживает сериализованные объекты PHP_CodeCoverage, он не работает с файлами XDebug cachegrind.

Я надеюсь, что смогу написать некоторый PHP, который импортирует выходной файл профилировщика XDebug (cachegrind.out) в объект PHP_CodeCoverage, а затем, следуя примеру в исходном коде PHPUnit, создать отчет в формате HTML. У кого-нибудь есть опыт профилирования запущенного PHP-приложения таким образом? Есть ли более простой способ сделать это?

Я хотел бы избежать использования PHP_CodeCoverage непосредственно в исходном коде моего приложения PHP, если это возможно.

1

Решение

Вы не можете получить детальные данные покрытия кода из анализа данных профилирования. Последний имеет только информацию о том, что функция или метод был выполнен. Хотя этого достаточно для расчета слабого варианта покрытия функции и покрытия метода, этого недостаточно, например, для получения тонкого покрытия линии.

2

Другие решения

Я сделал это с библиотекой PHP Code Coverage. Я создал объект и начал отслеживать покрытие кода в хуке CodeIgniter pre_system и записал отчет о покрытии в файл в хуке CodeIgniter post_system. Затем я создал скрипт для слияния объектов покрытия php и вывода их в виде HTML.

Я думал, что объединение файлов HTML будет возможно с phpcov, но я не мог объединить отчеты .html из-за отсутствующего файла «Шаблон». Я также был удивлен, обнаружив, что phpcov не позволяет вам указать формат вывода для объединенных файлов (то есть я мог объединить файлы .cov, но не смог вывести их в отчет .html).

Так вот мой код слияния, в основном просто продолжение этого поста, но его метод десериализации .cov файлов не работал для меня в PHP 5.3

<?php
/**
* "Deserializes" PHP_CodeCoverage objects from the files passed on the command line,
* combines them into a single coverage object and creates an HTML report of the
* combined coverage.
*/
require_once '/var/www/quickstart/vendor/autoload.php';

if ($argc <= 1) {
die("Usage: php generate-coverage-report.php cov-file1 [cov-file2 cov-    file3...]\n");
}

foreach (array_slice($argv, 1) as $filename) {
if (isset($codeCoverage)) {
// Reconstruct serialized output (from .cov file such as generated from 'phpunit --coverage-php')
$_coverage = include($filename);
// $codeCoverage->filter()->addFilesToWhitelist($_coverage->filter()->getWhitelist());
$codeCoverage->merge($_coverage);
unset($_coverage);
} else {
$codeCoverage = include($filename);
}
}

print "\nGenerating code coverage report in HTML format ...";

// Based on PHPUnit_TextUI_TestRunner::doRun
$writer = new PHP_CodeCoverage_Report_HTML(
'UTF-8',
false, // 'reportHighlight'
35, // 'reportLowUpperBound'
70, // 'reportHighLowerBound'
sprintf(
' and <a href="http://phpunit.de/"></a>'
//PHPUnit_Runner_Version::id()
)
);

$writer->process($codeCoverage, 'coverage');

print " done\n";
print "See coverage/index.html\n";
1