前言
考察目前关于单元测试和JUnit的文章,要么是介绍单元测试的理论,要么是通过一个简单的HelloWorld例子介绍工具的使用。这样很容易使读者在实际应用中无从下手。因为只有工具而没有理论的指导,将严重消弱了工具的作用,最终只能是沙滩建楼,达不到预期的目标;只有理论而没有工具的支持,也使得理论难有很好的着力点,最终使理论流于空泛。本文试图通过先讲解单元测试理论,进而将这些理论结合到JUnit的使用当中,最后通过对一个实用的、可以重用的时间操作类采用JUnit进行单元测试来完整阐述单元测试的思想、方法、以及工具的使用。作者相信,只有通过这样,才能让读者真正把单元测试做好。
1.简介
1.1. 为什么要进行单元测试
一个特定的开发组织或软件应用系统的测试水平取决于对那些未发现的Bug的潜在后果的重视程度。这种后果一方面常常会被软件的开发人员所忽视,而另一方面却有可能损害组织的信誉,并且会导致对未来的市场产生负面的影响。相反地,一个可靠的软件系统的良好的声誉将有助于一个开发组织获取未来的市场。
很多研究成果表明,无论什么时候作出修改都要进行完整的回归测试,在生命周期中尽早地对软件产品进行测试将使效率和质量得到最好的保证。Bug发现得越晚,修改它所需的费用就越高,因此从经济角度来看,应该尽可能早的查找和修改Bug。在修改费用变得过高之前,单元测试是一个在早期抓住Bug的机会。
相比后阶段的测试,单元测试的创建更简单、维护更容易,并且可以更方便的进行重复。 从全程的费用来考虑,相比起那些复杂且旷日持久的集成测试,或是不稳定的软件系统来说, 单元测试所需的费用是很低的。研究显示高达50%的维护工作量被花在那些总是会有的Bug的修改上面。如果这些Bug在开发阶段被排除掉的话,那么工作量就可以节省下来。当考虑到软件维护费用可能会比最初的开发费用高出数倍的时候,这种潜在的对50%软件维护费用的节省将对整个软件生命周期费用产生重大的影响。
1.2. 什么是单元测试
单元测试是对最小的可测试软件元素(单元)实施的测试,它所测试的内容包括内部结构(如逻辑和数据流)以及单元的功能和可观测的行为。这里的单元不一定是指一个具体的函数或一个类的方法,“单元”是:
(1)可测试的、最小的、不可再分的程序模块。
(2)有明确的功能、规格定义。
(3)有明确的接口定义,清晰地与同一程序的其他单元划分开来。
在具体实现时,单元测试也可能对应的是多个程序文件中的一组函数。在一种传统的结构化编程语言中,比如C,要进行测试的单元一般是函数或子过程。在象C++这样的面向对象的语言中,要进行测试的基本单元是类。单元测试的原则同样被扩展到第四代语言(4GL)的开发中,在这里基本单元被典型地划分为一个菜单或显示界面。
1.3. 单元测试的一般方法
单元测试的方法一般分为两类:白盒方法和黑盒方法。白盒方法通常是分析单元内部结构后通过对单元输入输出的用例构造,达到单元内程序路径的最大覆盖,尽量保证单元内部程序运行路径处理正确,它侧重于单元内部结构的测试,依赖于对单元实施情况的了解。
黑盒方法通过对单元输入输出的用例构造验证单元的特性和行为,侧重于核实单元的可观测行为和功能,并不依赖于对单元实施情况的了解。进行单元测试必须综合使用上述两个方法,否则,单元测试很可能就是不成功、不完整和不彻底的。
1.4. 单元测试的目标
单元测试要达到的目标,总体来说就是保证单元内部的处理是正确的、没有遗漏和多余功能。细分而言,单元测试要达到以下几个目标:
(1)信息能否正确地流入和流出单元。
(2)在单元工作过程中,其内部数据能否保持其完整性,包括内部数据的形式、内容及相互关系不发生错误,也包括全局变量在单元中的处理和影响。
(3)在为限制数据加工而设置的边界处,能否正确工作。
(4)单元的运行能否做到满足特定的逻辑覆盖。
(5)单元中发生了错误,其中的出错处理措施是否有效。
1.5. 为什么要使用JUnit进行单元测试
1.5.1. 什么是JUnit
原文转自:http://www.uml.org.cn/Test/201405272.asp