`
shangjava
  • 浏览: 1186522 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

PHPUnit袖珍指南 第十一章 残根

阅读更多
第十一章残根
相比有多个错误来源的测试,只测试一件事情的测试提供了更好的信息。如何隔离测试的外部影响呢?用来自简单的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的对象而不是依靠一个全局变量。残根模式鼓励这样的设计,它可以对象的偶合性,提高重用。
如果不熟悉自分流模式,测试可能难以阅读。这在做什么?为什么测试用例也是一个观察员?但是当你习惯了这些,测试就很容易阅读,所以你需要了解的测试都在一个类里。
--------------------------------------------------------------------------------------------------------------------
原文:
Chapter 11. Stubs
Tests that only test one thing are more informative than tests in which failure can come from many sources. How can you isolate your tests from external influences? Simply put, by replacing the expensive, messy, unreliable, slow, complicated resources with stubs made from plain PHP objects. For example, you can implement what is in reality a complicated computation by returning a constant, at least for the purposes of a single test.
Stubs solve the problem of allocating expensive external resources. For example, sharing a resource, such as a database connection, between tests by using the PHPUnit2_ Extensions_TestSetup decorator helps, but not using the database for the purposes of the tests at all is even better.
Design improvement is one effect of using stubs. Widely used resources are accessed through a single façade, so you can easily replace the resource with the stub. For example, instead of having direct database calls scattered throughout the code, you have a single Database objectan implementor of the IDatabase interface. Then, you can create a stub implementation of IDatabase and use it for your tests. You can even create an option for running the tests with the stub database or the real database, so you can use your tests for both local testing during development and integration testing with the real database.
Functionality that needs to be stubbed out tends to cluster in the same object, improving cohesion. By presenting the functionality with a single, coherent interface, you reduce the coupling with the rest of the system.
11-1. Self-Shunting
Sometimes you need to check that an object has been called correctly. You can create a complete stub of the object to be called, but that can make it inconvenient to check for correct results. A simpler solution is to apply the self-shunt pattern and use the test-case object itself as a stub. The term selfshunting is taken from the medical practice of installing a tube that takes blood from an artery and returns it to a vein to provide a convenient place for injecting drugs.
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:
class ObserverTest extends PHPUnit2_Framework_TestCase
implements Observer{
}
Next, we implement the one Observer method, update( ), to check that it is called when the state of the observed Subject object changes:
public $wasCalled = FALSE;
public function update(Subject $subject) {
$this->wasCalled = TRUE;
}
Now, we can write our test. We create a new Subject object and attach the test object to it as an observer. When the state of the Subject changesfor instance, by calling its doSomething( ) methodthe Subject object has to call the update( ) method on all objects that are registered as observers. We use the $wasCalled instance variable that is set by our implementation of update( ) to check whether the Subject object does what it is supposed to do:
public function testUpdate( ) {
$subject = new Subject;
$subject->attach($this);
$subject->doSomething( );
$this->assertTrue($this->wasCalled);
}
Notice that we create a new Subject object instead of relying on a global instance. Stubbing encourages this style of design. It reduces the coupling between objects and improves reuse.
If you are not familiar with the self-shunt pattern, the tests can be hard to read. What is going on here? Why is a test case also an observer? But once you get used to the idiom, the tests are easy to read. Everything you need to understand a test is in one class.
分享到:
评论

相关推荐

    PHPUnit袖珍指南.doc

    PHPUnit袖珍指南.doc PHPUnit 单元测试 从环境配置到 段元详细介绍

    PHPUnit袖珍指南之装置器

    编写测试最耗时的部分是边编写设置整个程序到达一个已知状态,而后在测试结束后返回到原始状态。这个已知状态叫做测试的装置器。本文将为大家介绍PHPUnit袖珍指南之装置器。

    PHPUnit PDF手册【袖珍指南】

    PHPunit pdf教程,非常不错,值得推荐

    PHPUnit袖珍指南之自动测试

    相比你正在使用的方法,采用PHPUnit进行测试并不是一个全然不同的东西。它们只是方法不同。两者之间的不同在于,检查程序行为是否符合正确是通过一批可以自动测试的代码片断来进行的。这些代码片断叫做单元测试。 在...

    PHPUnit袖珍指南之PHPUnit的目的

    当我们开始测试大量的array_*()函数时,每个都需要一个测试。我们可以每 个都从头写起。但是,更好的方法是一次性写好一个测试基础构架,以后就只用写每个测试不同的部分。PHPUnit就是这样一个基础构架。

    Etsy的PHPUnit扩展phpunit-extensions.zip

    phpunit-extensions 是 Etsy 的 PHPUnit 扩展。 标签:phpunit

    phpunit 4.2 最新版

    phpunit 3 67 最新版 PHPUnit是一个轻量级的PHP测试框架 它是在PHP5下面对JUnit3系列版本的完整移植 是xUnit测试框架家族的一员 它们都基于模式先锋Kent Beck的设计 单元测试是几个现代敏捷开发方法的基础 使得...

    PHPunit手册中文版

    本书讨论的是PHPUnit,一个用于采用PHP程序设计语言进行测试驱动开发的开源框架。本版次适用于3.2版的PHPUnit。当然,大多数示例应该也可用于2.0-3.1版的PHPUnit。本书后面的“用于PHP 4的PHPUnit”(附录B - 译注)...

    PHPUnit

    NULL 博文链接:https://tangzhifei.iteye.com/blog/437196

    phpunit配置及使用

    phpunit配置及使用

    phpunit_中文手册说明

    phpunit_中文手册说明 根据目录进行的编排!

    phpunit附属lib

    如果你在用PHPUNIT会报 include(PHPUnit_Extensions_Story_TestCase.php): failed to open stream: No such file or directory include(PHPUnit_Extensions_Database_TestCase.php): failed to open stream: No such...

    phpunit5.7

    PHPUnit 5.7 是之前旧的 稳定 版本。 它 稳定 于 2016年12月02日。 PHPUnit 5.7 支持于 PHP 5.6, PHP 7.0 和 PHP 7.1, PHPUnit 5 将于2018年02月02日结束维护支持。

    phpunit4.8.35

    phpunit.phar phpunit.cmd的打包文件

    PHPUnit单元测试的配置及使用

    PHPUnit单元测试的配置及使用,PHPUnit单元测试的配置及使用,PHPUnit单元测试的配置及使用,PHPUnit单元测试的配置及使用,PHPUnit单元测试的配置及使用

    ci-phpunit-test, 一种简单的使用 PHPUnit 3.x 语言的方法.zip

    ci-phpunit-test, 一种简单的使用 PHPUnit 3.x 语言的方法 ci-phpunit-test用于 CodeIgniter 3 。x 在 CodeIgniter 3. x. 中使用PHPUnit的简便方法你根本不需要修改CodeIgniter核心文件。你可以轻松编

    用于PHPUnit的花式testdox打印机

    用于PHPUnit的花式testdox打印机

    phpunit5.7官方文档PDF中文

    PHPUnit手册Sebastian Bergmann 此版本对应于PHPUnit 5.7。最后更新于2017-05026。 版权 2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015 Sebastian Bergmann

    phpunit-book.pdf

    该文档为 phpunit自动换测试文档。如果大家有什么问题希望大家回复。

    PHPUnit的并行测试库.zip

    PHPUnit的并行测试库

Global site tag (gtag.js) - Google Analytics