前面的一篇文章(单元测试------理论篇)讨论了什么是单元测试、单元测试的优点并列举了很多不写单元测试的借口。如果你同意我们的观点,认同单元测试确实是软件开发中不可缺少的过程,那么我们就开始单元测试之旅吧!
一个比较最大值的函数
我们首先引入一个比较最大值的函数。我们传入一个类型为int的数组参数,它将返回最大值的那个元素。代码如下:
public class Largest { public static int largest(int[] datas){ int max = 0; for(int i = 0 ; i < datas.length ; i++){ if(max < datas[i]){ max = datas[i]; } } return max; } } |
可是,如何写我们的测试代码呢?
直接在Largest类中添加一个main方法,要么重新写一个可运行的类来测试Largest。这样的测试,同样给我们带来了很大的挑战:
1、验证困难。如何去验证代码的行为和我们的期望一致呢?使用很多的if…else再加上==或equals()来判断?对异常的情况又如何处理呢?混乱的验证,很容易给我们的测试代码带来BUG,让我们对自己的测试不够自信。
2、测试类无法管理。我们如何直观的得到测试运行成功或失败的消息?用原始的System.out.println()吗?我们能一次运行多个单元测试吗?如果前面的测试运行出现异常,后面的测试还能继续运行吗?如果测试类很多,上百个甚至更多,我们能方便的由控制台输出测试结果吗?
3、无法统计测试代码覆盖情况。缺少统一的测试代码编写规范和约定,可读性和维护性差。
不过,面对这些挑战不用沮丧。单元测试框架已经帮我们解决了这些问题,它提供了很多测试的基础设施,让我们能把更多的经历投入到测试代码的编写中来。
JUnit
JUnit最初是由Erich Gamma(GoF之一)和Kent Beck(xp和refactor的先驱之一)编写的,它是一个开源的Java测试框架,用于编写和运行可重复的测试。
下面我们逐步介绍如何对Largest类测试:
一、JUnit的安装。如果你使用的开发工具是Eclipse,不用做任何安装,它已经提供了Junit的支持。否则,你需要去http://www.junit.org/下载Junit安装包。安装非常简单,只要将junit.jar包设置到ClassPath中,让你的Java代码能够找到它就可以了。
二、编写测试代码。代码如下:
public class LargestTest extends TestCase { public void testLargest(){ int[] datas = {7,8,9}; assertEquals(9,Largest.largest(datas)); } } |
说明:
1、测试类一般要继承抽象类TestCase。它实现了各种测试方法,并提供了一个测试过程的架构。
2、测试代码通过断言(Assert)来判断某个被测试函数是否正常工作。JUnit提供了很多断言函数,用来确定:某个条件是否为真;两个数据是否相等,或者不等,或者其它的一些情况。
3、测试方法名以“test”开头,这样JUnit框架会自动发现这是一个测试方法。
三、运行测试类。
运行测试成功。
我们的单元测试这样就算完成了吗?不,上面的测试只能算是一次验证而已。我们给的数据中,最大值9是数组的最后一个元素,如果9是第一个元素它还正确吗?如果数据是负数呢?等等。我们的求最大值函数有着很多的边界情况需要单元测试来验证。
因此,我们在写单元测试之前,一定要对测试做一个周全的计划,预先设置好要测试的内容,可能发生错误的边界条件。
下面是对Largest做的测试计划:
1、数组元素的位置是否对最大值产生影响?
[7,8,9] – 9
[7,9,8] – 9
[9,8,7] – 9
2、如果有两个相等的最大值,会出现什么情况呢?
[7,9,8,9] – 9
3、如果数组中只有一个元素,结果会怎么样?
[1] - 1
4、如果元素都是负数呢?
[-7,-8,-9] - -7
完整的测试代码应该如下:
public class LargestTest extends TestCase { public void testSimple(){ assertEquals(9,Largest.largest(new int[]{7,8,9})); } public void testOrder(){ assertEquals(9,Largest.largest(new int[]{7,9,8})); assertEquals(9,Largest.largest(new int[]{9,8,7})); } public void testDups(){ assertEquals(9,Largest.largest(new int[]{7,9,8,9})); } public void testOne(){ assertEquals(1,Largest.largest(new int[]{1})); } public void testNegative(){ assertEquals(-7,Largest.largest(new int[]{-7,-8,-9})); } } |