将文件添加到PHPUnit的`bootstrap.php`中的代码覆盖白/黑名单中

将文件添加到PHPUnit的`bootstrap.php`中的代码覆盖白/黑名单中,php,phpunit,code-coverage,Php,Phpunit,Code Coverage,PHP_CodeCoverage 1.1删除了PHP_CodeCoverage_过滤器的单例访问器,允许我们的PHPUnitbootstrap.PHP文件将目录添加到白名单/黑名单中。phpunit3.5使用黑名单从异常堆栈跟踪中剥离类,CC使用白名单限制跟踪。我们使用了这两个特性 如何从bootstrap.PHP文件中获取PHPUnit将使用的PHP\u CodeCoverage\u过滤器实例 注意:我们无法将它们放入phpunit.xml中,因为路径是从环境变量和配置文件构建的 更新:我发现

PHP_CodeCoverage 1.1删除了
PHP_CodeCoverage_过滤器
的单例访问器,允许我们的PHPUnit
bootstrap.PHP
文件将目录添加到白名单/黑名单中。phpunit3.5使用黑名单从异常堆栈跟踪中剥离类,CC使用白名单限制跟踪。我们使用了这两个特性

如何从
bootstrap.PHP
文件中获取PHPUnit将使用的
PHP\u CodeCoverage\u过滤器
实例

注意:我们无法将它们放入
phpunit.xml
中,因为路径是从环境变量和配置文件构建的


更新:我发现
PHPUnit\u Util\u Filter
不再使用代码覆盖率黑名单来过滤堆栈跟踪。这很好,因为这个类是为静态访问设计的,所以我可以添加一个方法将用户目录添加到列表中。这将是一个简单的改变,解决了这个问题的一半。

我问过Sebastian,他确认没有办法通过PHPUnit 3.6以编程方式访问CodeOverage_过滤器

我的建议是动态创建phpunit.xml,方法是创建一个模板,然后在填写配置文件后添加所需的
节点


不过,将来可能会有一种方法通过对测试运行程序进行子类化来注入PHP_CodeCoverage[\u Filter]对象。

这是一种难看的黑客行为,但它在PHPUnit 3.6中有效。我们已经有了自己的定制测试用例基类,其他所有人都可以扩展它。如果文件何时被添加到白名单并不重要,那么您可以使用一个假的测试用例来处理这个部分

首先,
bootstrap.php
根据需要多次调用BaseTestCase::AddxxxToCoDeCoraverageWhiteList(),以填充稍后要添加的文件的内部数组。接下来,要执行的第一个测试通过
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 && 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();
    }
}
更新:对于像我们一样使用黑名单阻止框架类出现在断言失败堆栈跟踪中的任何人,向上述类添加以下方法,并从
bootstrap.php
调用它们。这需要PHP5.3中的
setAccessible()

    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);
    }

它必须是env和config文件,还是仅仅是一个配置文件解决方案就足够了?(在我寻找一种方法的时候问一下)一个纯粹是环境变量(我们测试框架的位置)。另一种是
define()
与一些静态文本的组合。测试位于一个从源目录中完全删除的目录中,因此开发人员必须将源路径放入
config.php
中,而
bootstrap.php
自动包含该路径。今天早上我注意到(新的?)类
PHPUnit\u Util\u GlobalState
。这将是存储当前运行程序的好地方,它可以提供对正在使用的其他PHPUnit对象的访问。@DavidHarkness
PHPUnit\u Util\u GlobalState
是否有处理全局应用程序状态的方法(--backup globals)我昨天向Sebastian建议了类似的方法。在bootstrap f.e.中访问所需对象的方法。他说他正在考虑一种将这些对象注入自定义测试运行程序的方法。。这两个选项都可能有效,但遗憾的是,目前在3.6中,sightThanks中没有直接的共享解决方案!(getFilesForDirectory在这里做什么?我假设函数的状态是什么,但我不知道它是从哪里来的)哦,很好。我把它加在上面了。是的,它完全按照名字上说的做。:)谢谢我添加了允许您从断言失败堆栈跟踪中删除类的方法。这对于自定义断言和基本测试用例类很有用。