#php #phpunit #code-coverage
#php #phpunit #покрытие кода
Вопрос:
PHP_CodeCoverage 1.1 удалил средство доступа singleton для, PHP_CodeCoverage_Filter
которое позволяло нашим файлам PHPUnit bootstrap.php
добавлять каталоги в белые / черные списки. PHPUnit 3.5 использовал черный список для удаления классов из трассировок стека исключений, а CC использует белый список для ограничения отслеживания. Мы использовали обе эти функции.
Как я могу получить PHP_CodeCoverage_Filter
экземпляр, который PHPUnit будет использовать из bootstrap.php
файла?
Примечание: Мы не можем поместить их в phpunit.xml
, потому что пути создаются из переменных среды и файлов конфигурации.
Обновление: я вижу, что PHPUnit_Util_Filter
черный список покрытия кода больше не используется для фильтрации трассировок стека. Это нормально, и поскольку этот класс предназначен для статического доступа, я мог бы добавить метод для добавления пользовательских каталогов в список. Это было бы простым изменением и решило бы половину этого вопроса.
Комментарии:
1. Обязательно ли это должны быть env И конфигурационные файлы или будет достаточно решения только с файлом конфигурации? (Просто спрашиваю, пока я ищу способ сделать это)
2. Один из них является чисто переменной окружения (местоположение нашей платформы тестирования). Другой вариант — это комбинация
define()
с некоторым статическим текстом. Тесты находятся в каталоге, достаточно удаленном от исходного каталога, поэтому разработчик должен указать путь к исходному коду, вconfig.php
которыйbootstrap.php
автоматически включается.
Ответ №1:
Я спросил Себастьяна об этом, и он подтвердил, что нет способа получить программный доступ к CodeCoverage_Filter с PHPUnit 3.6.
Моим предложением было бы также создать phpunit.xml динамически, используя шаблон и затем заполняя добавление необходимых <directory>
узлов после заполнения файла конфигурации.
Возможно, в будущем будет способ внедрить объекты PHP_CodeCoverage[_Filter] путем создания подкласса для запуска тестирования.
Комментарии:
1. Я заметил (новый?) класс
PHPUnit_Util_GlobalState
этим утром. Это было бы отличным местом для хранения текущего бегуна, который мог бы обеспечить доступ к другим объектам PHPUnit в игре.2. @DavidHarkness Пока
PHPUnit_Util_GlobalState
есть, разбирайтесь с глобальным состоянием приложения (—backup globals) Вчера я предложил нечто подобное Себастьяну. Способ получить доступ к необходимым объектам в начальной загрузке, например. Он сказал, что думает о способе внедрения этих объектов в пользовательский тестовый запуск. оба варианта могут работать, но на данный момент с 3.6, к сожалению, прямого решения не видно
Ответ №2:
Это уродливый взлом, но он работает в PHPUnit 3.6. У нас уже есть наш собственный базовый класс тестового примера, который расширяют все остальные. Если не имеет значения, когда файлы будут добавлены в белый список, вы могли бы сделать это, используя поддельный тестовый пример только для обработки этой части.
Сначала bootstrap.php
вызывается BaseTestCase::addXXXToCodeCoverageWhitelist() столько раз, сколько необходимо для заполнения внутреннего массива файлов для последующего добавления. Далее, первый выполняемый тест добавляет эти файлы в фильтр покрытия кода через TestResult
.
abstract class BaseTestCase extends PHPUnit_Framework_TestCase
{
private static $_codeCoverageFiles = array();
public static function addDirectoryToCodeCoverageWhitelist($path) {
self::addFilesToCodeCoverageWhitelist(self::getFilesForDirectory($path));
}
public static function addFileToCodeCoverageWhitelist($path) {
self::addFilesToCodeCoverageWhitelist(array($path));
}
public static function addFilesToCodeCoverageWhitelist(array $paths) {
self::$_codeCoverageFiles = array_merge(self::$_codeCoverageFiles, $paths);
}
public static function getFilesForDirectory($path) {
$facade = new File_Iterator_Facade;
return $facade->getFilesAsArray($path, '.php');
}
private static function setCodeCoverageWhitelist(PHP_CodeCoverage $coverage = null) {
if ($coverage amp;amp; self::$_codeCoverageFiles) {
$coverage->setProcessUncoveredFilesFromWhitelist(true); // pick your poison
$coverage->filter()->addFilesToWhitelist(self::$_codeCoverageFiles);
self::$_codeCoverageFiles = array();
}
}
public function runBare() {
self::setCodeCoverageWhitelist($this->getTestResultObject()->getCodeCoverage());
parent::runBare();
}
}
Обновление: Для всех, кто использовал черный список, чтобы классы framework не отображались в трассировках стека ошибок утверждения, как это делали мы, добавьте следующие методы к вышеуказанному классу и вызовите их из своего bootstrap.php
. Для этого требуется setAccessible()
из PHP 5.3.
public static function ignoreDirectoryInStackTraces($path) {
ignoreFilesInStackTraces(self::getFilesForDirectory($path));
}
public static function ignoreFileInStackTraces($path) {
ignoreFilesInStackTraces(array($path));
}
public static function ignoreFilesInStackTraces($files) {
static $reflector = null;
if (!$reflector) {
PHPUnit_Util_GlobalState::phpunitFiles();
$reflector = new ReflectionProperty('PHPUnit_Util_GlobalState', 'phpunitFiles');
$reflector->setAccessible(true);
}
$map = $reflector->getValue();
foreach ($files as $file) {
$map[$file] = $file;
}
$reflector->setValue($map);
}
Комментарии:
1. Спасибо, что поделились! (Что здесь делает ‘getFilesForDirectory’? Я предполагаю, что именно указывает функция, но я не вижу, откуда это берется)
2. Упс, хороший улов. Я добавил это выше. Да, он делает именно то, что указано в названии. 🙂 Спасибо!
3. Я добавил методы, которые позволяют удалять классы из трассировок стека ошибок утверждения. Это полезно для ваших пользовательских утверждений и базовых классов тестовых примеров.