扩展PHPUnit:添加一个装饰器


Extending PHPUnit : adding a decorator

上下文

我最近继承了一个程序良好的PHP应用程序(sarcasm(的开发和维护。该应用程序基于一个商业软件(我不会说出它的名字(,并且有一层定制(我们的(构建在它的上面

不幸的是,这个应用程序使用了大量的全局和单态(双关语(。我已经为我们覆盖的所有内容构建了测试用例。然而,很多事情都依赖于某种全球状态,这可能会导致种族状况和各种奇怪的事情。

随机测试

为了捕捉这些怪人中的大多数(我喜欢这样称呼它们(,我构建了一个PHPUnit TestDecorator,[如手册中所述][1]。这个:

class PHPUnit_Extensions_Randomizer extends PHPUnit_Extensions_TestDecorator
{
    public function __construct(PHPUnit_Framework_Test $test)
    {
        $tests = $test->tests();
        $shuffle = array();
        foreach ($tests as $t) {
            if ($t instanceof PHPUnit_Framework_TestSuite) {
                $shuffle = array_merge($shuffle, $t->tests());
            } else {
                $shuffle[] = $t;
            }
        }
        shuffle($shuffle);
        $suite = new PHPUnit_Framework_TestSuite();
        foreach ($shuffle as $t) $suite->addTest($t);
        parent::__construct($suite);
    }
}

它基本上随机化测试顺序,以确保测试不依赖于可能正确也可能不正确的全局状态。

问题

当测试我的自定义装饰器时,问题出现了。我没有在手册、谷歌或堆栈溢出中找到任何地方如何加载它。

在分析代码时,我看到PHPUnit本身正在实例化TextUI_TestRunner::doRun()方法中的RepeatedTest装饰器。我知道我可以子类化TestRunner,覆盖doRun(),安排创建我的装饰器,然后用我的装饰实例作为参数调用parent::doRun(),覆盖TextUI_Command,创建一个新的CLI脚本来使用我的东西而不是内置的东西。

在我(重新(发明轮子之前,我只是想知道,是否可以在不子类化TestRunner的情况下加载自定义装饰器

谢谢。

对于当前的PHPUnit版本,在大多数情况下,没有简单的方法可以插入您自己的代码。唯一能提供互换性的是TestRunner,你所描述的对我来说很有意义

我不知道有任何其他方法可以提供测试装饰器或更改phpunit使用的大多数其他类。

你想要改变测试执行顺序的方式似乎是可行的,即使我不确定它会在多大程度上打乱套装。


实现这一点的另一种方法可能不那么麻烦,那就是在代码中随机创建PHPUnit_Framework_TestSuite的子类addTest


如果这不起作用,另一种选择是使用xml配置文件,并从<file>标签构建测试套件,在每次执行之前,都要对这些标签进行一些代码洗牌。Afaik phpunit不会以任何方式对它们进行排序,因此执行将是随机的


你是否想看看它上的每个测试是否真的有效,并想找到相互依赖的测试

或者,当你做了很多不应该以错误的顺序改变任何事情的事情时,你真的想看看是否有什么东西坏得很厉害吗?

我问你只是为了以防万一你还没有考虑--process-isolation。(我想你已经有了,但询问不会有什么坏处,可能会节省你一些时间和精力:(

当你用一组新的全局变量运行每个测试时,你至少会发现所有的测试相互依赖性,这只需要一个cli开关就可以确保套件中的每个测试都能正常工作。