- 第二章探索JUnit
- 第三章Junit实例
- 第四章-探索软件测试
- 第七章-使用mock objects进行孤立测试
- 第八章-使用cactus进行容器内的测试
- 第九章-对servlet和filter进行单元测试
- 第十一章-对数据库应用程序进行单元测试
- 第十二章-对EJB进行单元测试
- 参考资料
第二章探索JUnit
- Junit框架必须通过复用代码来降低测试代码的成本
第三章Junit实例
- 对还没有实现的测试代码抛出一个异常
抛出异常而不是返回控制(或者因为方法没有返回值而不返回任何值)。有两个好处:这样子可以让任何读代码的人都清楚知道这些方法还没有实现,并且可以确保如果方法被调用,他将会抛出异常,从而避免误以为是真正的行为。
@Test
public void testMethod(){
throw new RuntimeException("implements me");
}
- 一次只能单元测试一个对象
单元测试的一个至关重要的方面就是细粒度.一个单元测试独立的检查你创建的每一个对象,这样你就可以在问题发生的第一时间把它们隔离起来.如果被测试的对象多于一个,那么一旦这些对象发生了变化,你就无法预测它们将如何相互影响.当一个对象与其他复杂的对象交互时,你就可以使用可预测的测试对象将被测试的对象包围起来.
- 选择有意义的测试方法名字
一条好建议是测试方法的名字采用testXXX的命名模式,其中XXX是待测试领域方法的名字.当你需要为同一个方法添加其他测试时,则可以采用testXXXYYY的命名模式,其中YYY表示了测试之间的不同
- 在assert调用中解析失败原因
无论何时,只要你使用了JUnit的任何assertXXX方法,就要确保自己使用第一个参数为String类型的那个签名(如:assertNotNull(“Must not return a null result”,result)).这个参数让你可以提供一个用意义的文本描述,在断言失败时,JUnit的test runner就会显示这个描述.如果不使用这个参数,当测试失败时,要找出失败原因就会比较麻烦和困难了
- 一个单元测试等于一个@Test方法
为了获得最好的结果,你的测试方法应当尽量的简单明了和目的明确,不要试图把多个测试塞进一个方法.这样导致的结果就是测试方法变得更加复杂,难以阅读也难以理解,所谓理解万岁嘛,而且你在测试方法中编写的逻辑越多,测试失败的可能性就越高,甚至需要调试才能解决问题.这就会陷入一个滑坡,使得你很可能会堕入不得不为你的测试代码编写测试的深渊
- 始终使assert得到调用
当你测试的代码没有包含任何assert语句,执行测试时,JUnit会将它们标记为测试成功,但这只是一个自欺欺人的假象.记得要始终调用assert,唯一可以接受不实用assert调用的情况是当抛出一个异常来指出一个错误条件时.
-
迫使错误条件发生是测试灾难恢复能力的极佳做法
-
测试任何可能失败的事物
如果一个方法被改变了,变得不再简单,那么当发生这个改变时,你就应当为这个方法添加一个测试,但在改变之前方法简单得不会出错则不需要增加.
- 让测试改善代码
编写单元测试常常有助于你写成更好的代码。理由很简单,testcase是你的代码的用户,只有在使用代码的时候才能发现代码的缺点,所以应当根据测试时发现的不便之处重构代码,使其更易于使用。就类似TDD(测试驱动开发:要求程序员在自动测试失败的情况下编写新的代码,并且要消除重复),通过先编写测试,再从代码用户的角度来开发你的类。
- 让异常测试易读
把catch块中的异常变量命名为expected,这样就可以明确的告知读代码的人,这个异常是我们预期的,抛出异常才能让测试通过,在catch块中加入assertTrue(true)语句也进一步强调,这才是正确的执行路径。
- 同一个包,分离的目录
把所有测试类和待测类都放在同一个包中,但使用平行目录结构,为了可以访问保护型的方法,需要把测试和待测类放在同一个包中,为了简化文件管理,并让人清晰的分辨测试类和开发代码类,所有需要把测试放在一个单独的目录中。当然我们也可以使用一个test的包,进行遗漏所有开发包。这样也可以把test需要的resources文件也可也独立起来。
第四章-探索软件测试
- 考察单元测试的覆盖率
一种方法就是数一下你的测试中用到了多少方法。使用Clover工具进行覆盖率统计,记住100%的测试覆盖并不能保证你的应用程序得到了100%的测试。
- 测试先行
在写任何代码之前,必须先写一个失败的测试。为啥是失败的测试呢,因为不是失败的测试,老是成功的测试,你就不会改进这些代码来使其更加具有维护性。
- 三种单元测试
逻辑单元测试,集成单元测试,功能单元测试。逻辑单元测试主要是检查代码逻辑性,通常只是针对单个方法,一般可以通过mock objects 和stub 来控制特定的方法的边界。 集成单元测试主要是在真实环境下的一个组件相互交互的测试。功能单元测试目的是为了确认响应的结果是否正确,这种单元测试更多的依赖于外部环境。。
- 在开发周期的不同平台上执行的不同类型测试
第七章-使用mock objects进行孤立测试
- 不要把任何商业逻辑写入mock objects中
mock objects必须是容易创建和空壳(简单那得不可能出错)
- 只测试可能的错误
第八章-使用cactus进行容器内的测试
- 把cactus测试放在它们自己的目录中
大多数cactus test runner预期cactus测试会被放在一个单独的目录下,比如放在src/test-cactus目录中,因为他们需要和纯junit测试不同的环境(比如打包并部署到容器中,诸如此类)
第九章-对servlet和filter进行单元测试
- 记得检验测在应当失败的时候失败
总记得检验你写的测试能否正常工作,确保当你预期它失败时测试会失败。
- 使用TDD实现可以运作的最简设计
避免过多设计和实现,只要实现最少量的事情使测试能够通过,目的是完成一个完整的代码功能块,当你编写功能代码时就能引用测试代码。
第十一章-对数据库应用程序进行单元测试
- 在使用mock objects时重构冗长的设置代码
当使用mock objects时,如果在可调用待测方法之前所需执行的设置步数太多(没有正确使用mock objects、测试的代码职责太多),你就应当考虑重构。
第十二章-对EJB进行单元测试
- 在使用mock 重构测试的setUp和tearDown部分
当你要在一个特定的TestCase中编写更多的测试时,你最好花些时间对设置测试的公共代码进行重构(对于tearDown方法也是如此)。如果你不这样做,结果会使得你的测试变得非常复杂,没有人能轻易理解你的测试,并且很难进行维护,结果是失败的可能性会更大。
参考资料
1.《JUnit.in.Action中文版(第一版)》