我最近继承了一个编程良好的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);
}
}
它基本上随机化了测试顺序,以确保测试不依赖于可能正确或可能不正确的全局状态。
当来测试我的自定义装饰器时出现了问题。我没有在手册,谷歌或Stack Overflow中的任何地方找到如何加载它。
在分析代码时,我看到PHPUnit本身正在RepeatedTest
方法中实例化TextUI_TestRunner::doRun()
装饰器。我知道我可以继承TestRunner
,覆盖doRun()
,安排我的装饰器创建,然后只用我的装饰器实例作为参数调用parent::doRun()
,覆盖TextUI_Command
并创建一个新的CLI脚本来使用我的东西而不是内置的东西。
在我(重新)发明轮子之前,我只是想知道,是否可以加载自定义装饰器而无需继承TestRunner?
感谢。
答案 0 :(得分:3)
使用当前的PHPUnit版本,大多数情况下都没有简单的方法来插入您自己的代码。唯一能提供互换性的是TestRunner,你所描述的对我来说是有意义的。
我不知道有任何其他方式提供测试装饰器或更改phpunit使用的大多数其他类。
你想要改变测试执行顺序的方式似乎已经解决了,所以我不确定它会如何改变套装。
实现这一目标的另一种方法可能是减少麻烦,即随机PHPUnit_Framework_TestSuite
创建一个addTest
子类。
如果不能解决另一个选择,那就是使用xml配置文件并从<file>
标签构建测试套件,并且在每次执行之前都有一些代码对这些标签进行洗牌。 Afaik phpunit不会以任何方式对它们进行排序,因此执行将是随机的
或者你真的想看看当你做了很多不能以错误的顺序改变任何东西的东西时,某些东西是否可怕?
我问的是,如果你还没有考虑--process-isolation
。 (我假设你有,但问不会伤害,可能会节省你一些时间和精力:))
当您使用一组全局的全局变量运行每个测试时,您至少会找到所有测试相互依赖性,而这只是一个cli切换,以确保您的套件中的每个测试都能正常工作。