谈谈单元测试之(三):测试工具 JUnit 4


前言


上一篇文章《测试工具 JUnit 3》简单的讨论了 JUnit 3 的使用以及内部的方法。这篇文章将会在 JUnit 3 的基础上,讨论一下 JUnit 4 的新特性。同时,与 JUnit 3 做一个简单的对比。那么,废话就不多说了,直接进入正题。


介绍


JUnit 4.x 是利用了 Java 5 的特性(Annotation)的优势,使得测试比起 3.x 版本更加的方便简单,JUnit 4.x 不是旧版本的简单升级,它是一个全新的框架,整个框架的包结构已经彻底改变,但 4.x 版本仍然能够很好的兼容旧版本的测试用例。


使用


先来点实在的,看看代码中是怎么使用的。其余的待会再说。

下载



加入项目

  • 把 junit4.8.1.jar 文件,加入到项目的 classpath 中。


对比


在代码之前,先让我们看一下 JUnit 4 和 JUnit 3 的区别,看看 JUnit 4 到底简化了哪些东西。




演示代码

  1. <span style=“font-family:Microsoft YaHei;”>package com.tgb;  
  2.   
  3. import static org.junit.Assert.*;  
  4.   
  5. import org.junit.Ignore;  
  6. import org.junit.Test;  
  7.   
  8.   
  9. public class TestWordDealUtil {  
  10.     // 测试 wordFormat4DB 正常运行的情况  
  11.     @Test  
  12.     public void testWordFarmat4DBNormal() {  
  13.         String target = ”employeeInfo”;  
  14.         String result = WordDealUtil.wordFormat4DB(target);  
  15.           
  16.         assertEquals(”employee_info”, result);  
  17.     }  
  18.       
  19.     // 测试 null 时的处理情况  
  20.     @Test(expected=NullPointerException.class)  
  21.     public void testWordFormat4DBNull() {  
  22.         String target = null;  
  23.         String result = WordDealUtil.wordFormat4DB(target);  
  24.           
  25.         assertNull(result);  
  26.     }  
  27.       
  28.     // 测试空字符串的处理情况  
  29.     @Test  
  30.     public void testWordFormat4DBEmpty() {  
  31.         String target = ”“;  
  32.         String result = WordDealUtil.wordFormat4DB(target);  
  33.           
  34.         assertEquals(”“, result);  
  35.     }  
  36.       
  37.     // 测试当首字母大写时的情况  
  38.     //@Ignore  
  39.     @Test  
  40.     public void testWordFormat4DBBegin() {  
  41.         String target = ”EmployeeInfo”;  
  42.         String result = WordDealUtil.wordFormat4DB(target);  
  43.           
  44.         assertEquals(”_employee_info”, result);  
  45.     }  
  46.       
  47.     // 测试当尾字母大写时的情况  
  48.     @Test  
  49.     public void testWordFormat4DBEnd() {  
  50.         String target = ”employeeInfoA”;  
  51.         String result = WordDealUtil.wordFormat4DB(target);  
  52.           
  53.         assertEquals(”employee_info_a”, result);  
  54.     }  
  55.       
  56.     // 测试多个相连字母字母大写时的情况  
  57.     @Test  
  58.     public void testWordFormat4DBTogether() {  
  59.         String target = ”employeeAInfo”;  
  60.         String result = WordDealUtil.wordFormat4DB(target);  
  61.           
  62.         assertEquals(”employee_a_info”, result);  
  63.     }  
  64. }  
  65. </span>  
<span style="font-family:Microsoft YaHei;">package com.tgb;

import static org.junit.Assert.*;

import org.junit.Ignore;
import org.junit.Test;


public class TestWordDealUtil {
    // 测试 wordFormat4DB 正常运行的情况
    @Test
    public void testWordFarmat4DBNormal() {
        String target = "employeeInfo";
        String result = WordDealUtil.wordFormat4DB(target);

        assertEquals("employee_info", result);
    }

    // 测试 null 时的处理情况
    @Test(expected=NullPointerException.class)
    public void testWordFormat4DBNull() {
        String target = null;
        String result = WordDealUtil.wordFormat4DB(target);

        assertNull(result);
    }

    // 测试空字符串的处理情况
    @Test
    public void testWordFormat4DBEmpty() {
        String target = "";
        String result = WordDealUtil.wordFormat4DB(target);

        assertEquals("", result);
    }

    // 测试当首字母大写时的情况
    //@Ignore
    @Test
    public void testWordFormat4DBBegin() {
        String target = "EmployeeInfo";
        String result = WordDealUtil.wordFormat4DB(target);

        assertEquals("_employee_info", result);
    }

    // 测试当尾字母大写时的情况
    @Test
    public void testWordFormat4DBEnd() {
        String target = "employeeInfoA";
        String result = WordDealUtil.wordFormat4DB(target);

        assertEquals("employee_info_a", result);
    }

    // 测试多个相连字母字母大写时的情况
    @Test
    public void testWordFormat4DBTogether() {
        String target = "employeeAInfo";
        String result = WordDealUtil.wordFormat4DB(target);

        assertEquals("employee_a_info", result);
    }
}
</span>


从图中可以看出,TestWordDealUtil 测试类中,有6个测试方法,其中有5个测试方法都已经通过,另外一个抛出了 NullPointerException (空指针)异常,需要注意的是,这里并不是单元测试的失败(Failure),而是测试出现了错误(Error)。那么,这两种有什么区别呢?下面就讨论一下这两者的区别。

JUnit 将测试失败的情况分为两种:Failure 和 Error 。 Failure 一般是由单元测试使用的断言方法判断失败引起的,它表示在测试点发现了问题(程序中的 bug);而 Error 则是有代码异常引起的,这是测试目的之外的发现,它可能产生于测试代码本身的错误(也就是说,编写的测试代码有问题),也可能是被测试代码中的一个隐藏 bug 。不过,一般情况下是第一种情况。


深入


常用注解

  • @Before
初始化方法,在任何一个测试方法执行之前,必须执行的代码。对比 JUnit 3 ,和 setUp()方法具有相同的功能。在该注解的方法中,可以进行一些准备工作,比如初始化对象,打开网络连接等。

  • @After
释放资源,在任何一个测试方法执行之后,需要进行的收尾工作。对比 JUnit 3 ,和 tearDown()方法具有相同的功能。

  • @Test
测试方法,表明这是一个测试方法。在 JUnit 中将会自动被执行。对与方法的声明也有如下要求:名字可以随便取,没有任何限制,但是返回值必须为 void ,而且不能有任何参数。如果违反这些规定,会在运行时抛出一个异常。不过,为了培养一个好的编程习惯,我们一般在测试的方法名上加 test ,比如:testAdd()。

同时,该 Annotation(@Test) 还可以测试期望异常和超时时间,如 @Test(timeout=100),我们给测试函数设定一个执行时间,超过这个时间(100毫秒),他们就会被系统强行终止,并且系统还会向你汇报该函数结束的原因是因为超时,这样你就可以发现这些 bug 了。而且,它还可以测试期望的异常,例如,我们刚刚的那个空指针异常就可以这样:@Test(expected=NullPointerException.class)。再来看一下测试结果。



  • @Ignore
忽略的测试方法,标注的含义就是“某些方法尚未完成,咱不参与此次测试”;这样的话测试结果就会提示你有几个测试被忽略,而不是失败。一旦你完成了相应的函数,只需要把 @Ignore 注解删除即可,就可以进行正常测试了。当然,这个 @Ignore 注解对于像我这样有“强迫症”的人还是大有意义的。每当看到红色条(测试失败)的时候就会全身不舒服,感觉无法忍受(除非要测试的目的就是让它失败)。当然,对代码也是一样,无法忍受那些杂乱不堪的代码。所以,建议大家都写漂亮的代码。这样人人都喜欢看你的代码。哎,有强迫症的人伤不起啊!

  • @BeforeClass
针对所有测试,也就是整个测试类中,在所有测试方法执行前,都会先执行由它注解的方法,而且只执行一次。当然,需要注意的是,修饰符必须是 public static void xxxx ;此 Annotation 是 JUnit 4 新增的功能。

  • @AfterClass
针对所有测试,也就是整个测试类中,在所有测试方法都执行完之后,才会执行由它注解的方法,而且只执行一次。当然,需要注意的是,修饰符也必须是 public static void xxxx ;此 Annotation 也是 JUnit 4 新增的功能,与 @BeforeClass 是一对。


执行顺序


所以,在 JUnit 4 中,单元测试用例的执行顺序为:



每一个测试方法的调用顺序为:





规范


最后,在来说说关于测试的规范,这些规范是从编程规则,以及日常的实践中,由那些大牛们总结出来的。作为后人的我们,在大树下乘凉的同时,更要遵守这些规则,使得大树更加茁壮成长。
  • 单元测试代码应位于单独的 Source Folder 下
此 Source Folder 通常为 test ,这样可以方便的管理业务代码与测试代码。其实,在项目管理工具 Maven 上已经做了这种规范了。在我们自己写代码时,注意一下即可。



  • 测试类应该与被测试类位于同一 package 下
便于进行管理,同时减少引入带测试类的麻烦。



  • 选择有意义的测试方法名
无论是 JUnit 4 ,还是 JUnit 3 ,单元测试方法名均需使用 test<待测试方法名称>[概要描述] ,如 public void testDivideDivisorIsZero() ,很容易知道测试方法的含义。

  • 保存测试的独立性
每项单元测试都必须独立于其他所有单元测试而运行,因为单元测试需能以任何顺序运行。

  • 为暂时未实现的测试代码忽略(@Ignore)或抛出失败(fail)
在 JUnit 4 中,可以在测试方法上使用注解 @Ignore 。在 JUnit 3 中,可以在未实现的测试方法中使用 fail(“测试方法未实现”); 以告知失败是因为测试方法未实现。

  • 在调用断言(assert)方法时给出失败的原因
在使用断言方法时,请使用带有 message 参数的 API ,并在调用时给出失败时的原因描述,如 assertNotNull(”对象为空”, new Object())。


结束语


请牢记:测试任何可能的错误。单元测试不是用来证明您是对的,而是为了证明您没有错。

JUnit 4 到这里就差不多了,如果文章中有什么不对的地方,还希望各位大牛拍砖。说了这么多,能真正用上才是王道,当然,希望以我这篇文章为契机,IT 界的精英们,之前没有用单元测试的,能够唤醒你们体内的小宇宙;之前已经在用的,也能够再体会一番,提高开发的效率,写出 漂亮 的代码。


资料:本文中的Demo(下载地址


【原创】地址:http://blog.csdn.net/happylee6688/article/details/38069761这里写链接内容

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值