背景
最近,我接手了一款程序良好的 PHP 应用程序(讽刺),该应用程序基于商业软件(我不会透露名称),并且有一个我们构建的自定义层。
不幸的是,这个应用程序使用了大量的全局变量和单例模式(意图明显)。我已经为我们覆盖的所有内容构建了测试用例。然而,很多事情依赖于某些全局状态,这可能会导致竞态条件和各种奇怪的问题。
随机化测试
为了捕获大部分这些怪异的问题(我喜欢称之为“怪人级别”),我已经按照[手册中的文档][1]构建了一个 PHPUnit TestDecorator
。它是这样的:
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);
}
}
该方法的基本作用是随机化测试顺序,以确保测试不依赖于可能正确或不正确的全局状态。
问题
当测试自定义装饰器时,出现了问题。我没有在手册、Google或Stack Overflow中找到如何加载它的任何信息。
在分析代码时,我发现PHPUnit自身在TextUI_TestRunner::doRun()
方法中实例化了RepeatedTest
装饰器。我知道可以子类化TestRunner
,覆盖doRun()
,安排创建我的装饰器,然后只需使用我的装饰器实例作为参数调用parent::doRun()
,重写TextUI_Command
并创建一个新的CLI脚本来使用我的东西而不是内置的东西。
在重新发明轮子之前,我只是想知道:有没有可能在不子类化TestRunner的情况下加载自定义装饰器?
谢谢。