Добавить файлы в белые / черные списки с покрытием кода в `bootstrap.php ` для PHPUnit

#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. Я добавил методы, которые позволяют удалять классы из трассировок стека ошибок утверждения. Это полезно для ваших пользовательских утверждений и базовых классов тестовых примеров.