单元测试整理(二)——断言篇,首个单元测试程序

引子

单元测试主要是用来验证所测代码是否和程序员的期望一致,如下所示,在实际操作中,我们可以编写一个函数assertTure()来验证预期条件是否满足,也可以进一步编写一个函数assertEquals()来判断两个数是否相等。事实上诸如此类判断函数,我们称之为断言。

public void assertTrue(boolean condition){
    if(!condition){
        abort();
    }
}
--------------------------------------------
int a = 5;
//如果由于某种原因,当调用assertTrue()的时候,a并不等于5,上面程序将终止
assertTure(a == 5);
public void assertEquals(int a, int b){
    assertTrue(a == b);
}

断言 是一种放在程序中的一阶逻辑(如一个结果为真或是假的逻辑判断式),目的是为了标示与验证程序开发者预期的结果-当程序运行到断言的位置时,对应的断言应该为真。若断言不为真时,程序会中止运行,并给出错误消息1

常用断言

序号方法描述描述
1void assertEquals(boolean expected, boolean actual)检查两个变量或者等式是否平衡
2void assertTrue(boolean expected, boolean actual)检查条件为真
3void assertFalse(boolean condition)检查条件为假
4void assertNotNull(Object object)检查对象不为空
5void assertNull(Object object)检查对象为空
6void assertSame(boolean condition)检查两个相关对象是否指向同一个对象
7void assertNotSame(boolean condition)检查两个相关对象是否不指向同一个对象
8void assertArrayEquals(expectedArray, resultArray)检查两个数组是否相等

上表列举了常用的八种断言,事实上我们在实际使用中并不需要自己编写这些基础的断言,java的编程框架JUnit已经集成了这些断言和一系列单元测试相关的函数。
JUnit 是一个 Java 编程语言的单元测试框架(回归测试框架)。JUnit 在测试驱动的开发方面有很重要的发展,是起源于 JUnit 的一个统称为 xUnit 的单元测试框架之一。JUnit 促进了“先测试后编码”的理念,强调建立测试数据的一段代码,可以先测试,然后再应用。这个方法就好比“测试一点,编码一点,测试一点,编码一点……”,增加了程序员的产量和程序的稳定性,可以减少程序员的压力和花费在排错上的时间2

第一个单元测试程序

我们将从这样一个简单的例子开始:查找一个list中的最大值。这次我们不妨用一种先想测试,再写代码的编程思想。
1,首先,这个程序要保证一个list,如{7,8,9},可以把9输出出来
2,然后呢,上面给了一个顺序的list,不失一般性,这个程序不应该是顺序敏感的,所以{7,9,8},{9,8,7}等也要输出9
3,我发现,上面的list都是正数,那么负数和0呢?{-7,-8,-9}应该返回-7吧。
4,等等,如果list里面有重复项呢?{7,9,8,9}应该只返回一个9就可以了
5,那么,如果list里面只有一个元素呢?{9}当然是返回9了
6,考虑完了?空值呢?如果list为空,{ }要怎么处理呢?
总结:1+2+5->注意上下界;3->max的初始值应为一个数型最小值;4->记录且return一个max;6->抛个异常
代码如下:

//Largest.java
public class Largest {
    public static int largest (int[] list) {
        int max=Integer.MIN_VALUE;
        if(list.length == 0) {
            throw new RuntimeException("Empty list");
        }
        for(int i=0;i<list.length;i++) {
            if(list[i]>max) {
                max = list[i];
            }
        }
        return max; 
    }
}

事实上上述代码的测试代码就是考虑了最开始那6个测试例子,加以实现:

//LargestTest.java
import junit.framework.*;
public class LargestTest extends TestCase {
    public LargestTest(String name) {
        super(name);
    }
    //test numbers
    public void testNums() {
        //general test
        assertEquals(9, Largest.largest(new int[] {7,8,9}));
        //order test
        assertEquals(9, Largest.largest(new int[] {7,9,8}));
        assertEquals(9, Largest.largest(new int[] {9,8,7}));
        //repetition test
        assertEquals(9, Largest.largest(new int[] {7,9,8,9}));
        //single test
        assertEquals(9, Largest.largest(new int[] {9}));
        //negative test
        assertEquals(-7, Largest.largest(new int[] {-7,-8,-9}));
    }
    //test empty
    public void testisEmpty() {
        try {
            Largest.largest(new int[] {});
            fail("An exception should been thrown!");
        }catch(RuntimeException e) {
            assertTrue(true);
        }
    }
}

注:1,如果import junit.framework.*;报错是因为没有导入junit的jar包。可以Eclipse中:右键工程名–>属性–>Java Build Path–>Libraries–>Add Library,选中JUnit导入,版本随意。
2,相关代码可以直接在我的Github下载,欢迎star。

做一个简单的总结,测试代码必须要做以下几件事:
1,准备测试所需要的各种条件(创建所有必须的对象,分配必要的资源等等)
2,调用要测试的方法
3,验证被测试方法的行为和期望是否一致
4,完成后清理各种资源(第三章讲)

JUnit 测试骨架

下面是一段简单的测试代码,它展示了让一段断言方法所需要的骨架的最小要求

import junit.framework.*;
public class FrameTest extends TestCase {
    public FrameTest(String name) {
        super(name);
    }
    public void testFrame(){
        ...
    }
}

尽管上面的代码非常简洁,还是要简单解释下每一部分
1,首先,第一行的import声明引入了必需的JUnit类。
2,接下来在第2行定义了一个类:每个包含测试的类都必须如上所示那样有TestCase继承而来。基类TestCase提供了我们所需的大部分单元测试功能,包括所有在前面讲述过的断言方法。
3,其中,基类需要一个以String为参数的构造函数,因而我们必须调用super来传递这么一个名字。我们不知道这个名字此时是什么,因而我们就仅仅让我们自己的构造函数接受String参数并把这个参数在第4行传递上去。
4,最后,测试类包含了名为test的方法。在上面这个例子中,我们在第6行写了一个名为testFrame的方法。而所有以test开头的方法都会被JUnit自动运行。当然,还可以通过定义suite方法制定特殊的函数来运行(第三章讲)。

在下一章单元测试整理(三)——JUnit 测试组成和注释将进一步展示更完整的JUnit骨架,介绍一些复杂一点的辅助测试方法。

  • 5
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值