第十一章残根
相比有多个错误来源的测试,只测试一件事情的测试提供了更好的信息。如何隔离测试的外部影响呢?用来自简单的PHP对象的残根替代昂贵, 杂乱, 不可靠, 缓慢, 复杂的资源。例如,为了单项测试的目的,你可以通过返回常数的方法来代表实际上很复杂的计算。
残根很好的解决了分配昂贵的外部资源的问题。例如,共享资源,在测试之间可以使用PHPUnit2 _ Extensions_TestSetup共享数据库连接,但是根本不使用为了测试目的的数据库更好。
改善设计是使用残根的一项效果。各种被使用的资源通过一个简单的面来访问,这样,用残根很容易实现资源替换。例如,不要在代码中到处进行数据库调用,而是实现一个简单的Idatabase接口。然后,就可以创建一个残根,实现Idatabase接口,用它来服务测试。甚而可以创建一个选项,选择使用数据库残根还是真正的数据库,这样测试既可以作为开发时的本地测试,也可以和真实的数据库进行集成测试。
需要形成残根的功能倾向于聚在一个对象中,以改进内聚性。用一个简单,内聚的接口来向外展示功能,你可以减少和系统其余部分的偶合性。
11-1.自分流
有时需要检查对象是否被正确地调用,你可以创建对象的完整残根用于调用,但那可能使它不便于检查调用的结果是否正确。一种更加简单的方案是使用自分流模式,把测试用例自身作为残根。术语自分流是从医学实践借用的术语,它指在动脉和静脉之间安装导管,从动脉引出血液并返回静脉,这可以注射药物。
Here is an example: suppose we want to test that the correct method is called on an object that observes another object. First, we make our test-case class an implementor of Observer:
以下是个例子:假设我们想要测试观察其它对象的对象是否被正确方法调用。首先,实现测试用例的Observer接口:
class ObserverTest extends PHPUnit2_Framework_TestCase
implements Observer{
}
其次, 我们实现Observer的方法update(),检查当它观察的对象的状态改变时,update()是否被调用:
public $wasCalled = FALSE;
public function update(Subject $subject) {
$this->wasCalled = TRUE;
}
现在,可以写测试了。创建一个新的Subject对象,将测试对象附带在对象上作为观察员。但Subject的状态改变时,如调用doSomething()方法,Subject对象就会调用所有注册为观察员的update()方法。通过实现update(),我们用$wasCalled变量来检查Subject是否做了它应该做的事。
public function testUpdate( ) {
$subject = new Subject;
$subject->attach($this);
$subject->doSomething( );
$this->assertTrue($this->wasCalled);
}
注意, 我们创建一个新的Subject的对象而不是依靠一个全局变量。残根模式鼓励这样的设计,它可以对象的偶合性,提高重用。
如果不熟悉自分流模式,测试可能难以阅读。这在做什么?为什么测试用例也是一个观察员?但是当你习惯了这些,测试就很容易阅读,所以你需要了解的测试都在一个类里。
--------------------------------------------------------------------------------------------------------------------
查看本文来源