扩展PHPUnit:添加装饰器

net*_*der 9 php phpunit

上下文

我最近继承了一个编程良好的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);
    }
}
Run Code Online (Sandbox Code Playgroud)

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

这个问题

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

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

在我(重新)发明轮子之前,我只是想知道,是否有可能在没有继承TestRunner的情况下加载自定义装饰器?

谢谢.

edo*_*ian 3

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

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

即使您想要更改测试执行顺序的方式似乎可行,但我不确定它会如何洗牌。


实现这一目标的另一种可能更少麻烦的方法是PHPUnit_Framework_TestSuite随机创建addTest代码的子类。


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


您是否想查看其上的每个测试是否真的有效并想要找到相互依赖的测试?

或者你真的想看看当你做了很多不应该以错误的顺序改变任何东西的事情时,是否会出现严重的问题?

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

当您使用一组新的全局变量运行每个测试时,您至少会发现所有测试的相互依赖关系,并且只需一个 cli 切换即可确保套件中的每个测试都能正常工作。