首页 > 技术文章 > JAVA Junit4

fqwsndc1314-5207788 2017-05-19 20:13 原文

                               JAVA     Junit4   测试框架

 

 序言

 

       刚学Java的时候就听说过JUnit了,单元测试框架,很好用的测试框架,JUnit测试框架将测试更加便捷和容易,编写测试代码也是简单、明了,功能强大。今天我给大家简单分享一下最新JUnit4的使用,几分钟入门!

 

导入jar包

 

      在集成开发环境中导入相应jar包:junit-4.12.jar、hamcrest-core-1.3.rc2.jar、hamcrest-library-1.3.rc2.jar。如果只导入第一个jar的话就不能启动测试程序会报错,报错及几个包的关系详见我的博客:JUnit4单元测试报错。在此,给大家提供一下这几个jar包的免费下载链接:

 

junit-4.12.jar下载

 

hamcrest-library-1.3.rc2.jar下载

 

hamcrest-core-1.3.rc2.jar下载

 

       导入方法看如下截图就明白了:

 

 

 

 

新建测试用例

 

       右击包名,点击新建,或者新建里的others,选择JUnit test case,如下图所示:

 

 

 

 

 

 

接下来,给测试类起名字和选择要测试的类,如下图所示:

 

 

 

 

然后点击【Next】,选择要被测试类中的测试方法,如下图所示:

 

 

 

 

最后新建完成,如下(第一个方法是生成的方法,后边几个都是我自己手动写上去的):

 

  1. package JUnitTest;  
  2.   
  3. import static org.junit.Assert.*;  
  4.   
  5. import org.junit.After;  
  6. import org.junit.AfterClass;  
  7. import org.junit.Before;  
  8. import org.junit.BeforeClass;  
  9. import org.junit.Ignore;  
  10. import org.junit.Test;  
  11.   
  12. public class TestJava {  
  13.   
  14.     @Test  
  15.     public void testMain() {  
  16.         fail("Not yet implemented");  
  17.     }  
  18.   
  19.     @Test  
  20.     public void testTest() {  
  21.         System.out.println("@Test");//调用自己要测试的方法  
  22.     }  
  23.       
  24.     @Test  
  25.     public void testAssert() {  
  26.         assertEquals("chenleixing","chenlei");  
  27.     }  
  28.       
  29.     @Test(timeout=1)  
  30.     public void testTimeout() {  
  31.         System.out.println("超时测试");  
  32.     }  
  33.   
  34.     @Before  
  35.     public void testBefore(){  
  36.         System.out.println("@Before");  
  37.     }  
  38.       
  39.     @BeforeClass  
  40.     public static void testBeforeClass(){//必须为静态方法  
  41.         System.out.println("@BeforeClass");  
  42.     }  
  43.       
  44.     @After  
  45.     public void testAfter(){  
  46.         System.out.println("@After");  
  47.     }  
  48.       
  49.     @AfterClass  
  50.     public static void testAfterClass(){//必须为静态方法  
  51.         System.out.println("@AfterClass");  
  52.     }  
  53.       
  54.     @Ignore  
  55.     public void testIgnore(){  
  56.         System.out.println("@Ignore");  
  57.     }  
  58. }  

 


JUnit4注解解释

 

1. @Test : 测试方法,测试程序会运行的方法,后边可以跟参数代表不同的测试,如(expected=XXException.class) 异常测试,(timeout=xxx)超时测试
2. @Ignore : 被忽略的测试方法
3. @Before: 每一个测试方法之前运行
4. @After : 每一个测试方法之后运行
5. @BeforeClass: 所有测试开始之前运行
6. @AfterClass: 所有测试结束之后运行
fail方法是指测试失败

 

assertEquals测试2个参数是否相等,具体参考相应API

 

更多方法可参考相应API文档(博文末尾分享下载连接给大家)

 

运行测试用例

 

       把自己的测试代码写在@Test注解后者其他注解的方法里边,点击运行新建的测试用例,结果如下:

 

 

 

 

带差号的是说明测试失败的,testMain()和testAssert()肯定会失败,对号的是测试成功的。

 

控制台输出的结果如下:

 

  1. <span style="font-size:18px;">@BeforeClass  
  2. @Before  
  3. 超时测试  
  4. @After  
  5. @Before  
  6. @After  
  7. @Before  
  8. @Test  
  9. @After  
  10. @Before  
  11. @After  
  12. @AfterClass</span>  

 

免费下载jar包和文档

 

junit-4.12.jar下载

 

hamcrest-library-1.3.rc2.jar下载

 

hamcrest-core-1.3.rc2.jar下载

 

junit4API.chm.html下载

 

JUnit4高级篇及更加的详细深入的使用,请参考:JUnit4高级篇-由浅入深。

 

 

第一步:

 

打开eclipse.exe,创建一个名为“Ives”的工项目,创建一个名为”UnitTest”的类。写几个方法:两数+ - * /的方法和返回结果的方法。

 

代码如下:

 

 1 import java.util.*;
 2 public class Expression {
 3     int a;
 4     int b;
 5     static int c;//用户答案
 6     int answer;//答案
 7     static Scanner in=new Scanner(System.in);
 8 
 9 
10 public int Expression(){
11     a = new Random().nextInt()%10;
12     b = new Random().nextInt()%10;
13     System.out.print(""+a+"+"+b+"=");
14     return answer = a + b;
15 
16 }
17 public static void main(String[] args){
18     int answer;
19     Expression expression = new Expression();
20     answer = expression.Expression();
21     try{
22         Expression.c = in.nextInt();
23     }
24     catch(InputMismatchException e)
25     {   System.err.println("\nError  ,please Enter a Int number");
26     }
27     if(answer==c)
28     {
29         System.out.print("答对了");
30     }
31     else System.out.print("答错了");
32     //System.out.print("answer="+answer);
33 }
34 }
View Code

 

第二步:

 

Duang!酷炫的效果来了,跟紧脚步了。

 

JUnit4 单元测试包引入这个项目:在该项目“Ives”上点右键,点“属性”(Pr o perties),如图:

 

在弹出的属性窗口中,首先在左边选择“Java 构建路径 (Java Build Path) 然后到右上选择"库(L)"( Libraries )标签,之后在最右边点击“添加库(A) ”(Add Libraries) 按钮,如下图所示:

 

 

点击完成, JUnit4 软件包就被包含进我们这个项目了。

 

第三步:

 

生成 JUnit 测试框架:在 Eclipse 的包资源管理器( Package Explorer) 中用右键点击该类”UnitTest“弹出菜单,选择 新建 →JUnit测试用例 ( New à JUnit Test Case )。如下图所示:

 

 

在弹出的对话框中,进行相应的选择,如下图所示:

 

 

点击完成之后会出现如下图:

 

 

千万不要去删除@Test这个标志很重要的!!!!!然后把fail(“尚未实现”)删除,把自己的代码敲进去就可以了。我选择了测试4个方法,所以它会自动生成4个测试方法。

 

Duang!!!

 

那测试方法怎么写呢?举个例子,我想知道我的UnitTest里面的plus方法有没有写对,那我就对这个方法写个测试。把a,b两个数传递进去,例如a=1和b=1,那a+b就等2,所以这里我们又要了解新的东西了。那就是关于JUnit 的api了,下面有关于JUnit的api,到时候我看看要不要贴几个常用的方法出来,加上实例,这样会更加容易理解。

 

继续我们的话题:我们知道a+b=2,所以如果plus方法的result是2的话,那就说明了我们的这个plus暂时没有这类型的bug。所以我们要用到方法 assertEquals(double expected, double actual) 这个方法里的double expected是我们期望的值,double actual是实际的值。例如assertEquals(2, a+b),这样就可以测试方法有没有算错了。其实电脑一般都不会算错吧?哈哈

 

完整的测试代码如下:

 

 1 import static org.junit.Assert.*;
 2 import org.junit.Test;
 3 
 4 public class UnitTestTest {
 5     public static UnitTest puls = new UnitTest();
 6     public static int answer;
 7     @Test
 8     public void testPlus() {
 9         puls.plus(1,1);
10         assertEquals(2, puls.getresult());
11     }
12 
13     @Test
14     public void testMinus() {
15         puls.minus(1,1);
16         assertEquals(0, puls.getresult());
17     }
18     
19     @Test
20     public void testMultiply() {
21         puls.multiply(1,1);
22         assertEquals(1, puls.getresult());
23         
24     }
25     
26     @Test(expected=ArithmeticException.class)
27     public void testDivide1(){
28         puls.divide(0, 1);
29     }
30     
31     @Test
32     public void testDivide() {
33         puls.divide(1,1);
34         assertEquals(1, puls.getresult());
35     }
36 }
View Code

 

可能用心看的童鞋可能会发现我还写了一个测试时关于有没有抛出异常的。如果除数为0那就抛出异常,再去测试它除数为0是有没有抛出异常。有人可能会问,我不知道什么异常啊,很简单,看

 

 

我们写完代码,那么唰唰唰的快感马上就要到来了。

 

 

 

我把minus方法里的“减号”改成了“加号”:如下图

 

 

然后在运行测试类UnitTestTest.如下图:

 

 

被测试的代码有bug,也就是之前把-修改成了+,所以就会出故障。

 

所以当全部都是绿色的时候是不是很爽,有没有感受到割草机(JUnit4)的唰唰唰的快感。

 

 

接下来介绍一下什么是JUnit?

Junit最初是由Erich Gamma和Kent Beck编写的一个回归测试框架(regression testing framework),为单元测试(Unit Test)的支持框架,用来编写和执行重覆性的测试,即所谓白盒测试,Junit是一套框架,继承TestCase类,就可以用Junit进行自动测试了

Junit的简单的环境配置:

在Eclipse中选择项目Junit4(在Package Explorer中)—>右击鼠标—>选择properties—>选择Java Build Path(在左边的菜单中)—>在右边选标签 Libraries->单击按钮“Add Library”—>选JUnit,单击“Next>”—>选择JUnit library version为:JUnit4—>单击按钮“Finish”––>单击按钮“OK”

JUnit4的基础知识介绍

JUnit4的常用注解:

@Test:测试方法,测试程序会运行的方法,后边可以跟参数代表不同的测试,如(expected=XXException.class)异常测试,(timeout=xxx(毫秒))超时测试
@BeforeClass:它会在所有的方法运行前被执行,static修饰
@AfterClass:它会在所有的方法运行结束后被执行,static修饰
@Before:会在每一个测试方法被运行前执行一次,初始化方法
@After:会在每一个测试方法运行后被执行一次,释放资源
@Ignore:所修饰的测试方法会被测试运行器忽略
@RunWith:可以更改测试运行器,可以自己设置运行器,只需要继承org.junit.runner.Runner这个类就行
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

JUnit4的常用方法:

fail()方法:是指测试失败
assertEquals()方法:测试2个参数(一个是预期值,一个是实际值)是否相等
  • 1
  • 2
  • 1
  • 2

其他方法看这篇文档:(在线文档-junit-4.10):http://tool.oschina.net/apidocs/apidoc?api=junit-4.10

JUnit4的运行流程介绍:

1.@BeforeClass修饰的方法会在所有方法被调用前被执行,而且该方法是静态的,所以当测试类被加载后接着就会运行它,而且在内存中它只会存在一份实例,它比较适合加载配置文件,进行初始化等等

2.@Before和@After会在每个测试方法的前后各执行一次

3.@AfterClass所修饰的方法会在所有方法被调用后被执行,通常用来对资源的清理,如关闭数据库的连接

JUnit4的基本使用介绍

在写测试代码时这里有几点值得注意:

1.测试方法上必须使用@Test进行修饰
2.测试方法必须使用public void修饰,不带任何参数
3.新建一个源码目录(如test)来存放我们的测试代码
4.测试类的包应该和被测试类保持一致
5.建议测试类使用Test作为类名的后缀,测试方法使用test作为方法名的前缀
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5

JUnit4之超时测试的使用:

通过@Test 注解中,为timeout参数指定时间值,即可进行超时测试,如果测试运行时间超过指定的毫秒数,测试失败,超时测试对网络链接类非常重要,通过timeout 进行超时测试非常简单

@Test(timeout=2000) //2000ms
public void testWhile(){
    while(true){
        System.out.println("run....");
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

JUnit4之异常测试的使用:

在进行单元测试的时候有的时候需要测试某一方法是否抛出了正确的异常,我们希望在单元测试中通过测试保证该方法会正确的抛出正确类型的异常

@Test(excepted=ArithmeticException.class)
public void testDivide(){
    c.divide(2/0);
}
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

JUnit4测试套件的介绍和使用:

在介绍之前首先我们来看看@RunWith:

当类被@RunWith注解修饰,或者类继承了一个被该注解修饰的类.JUnit将会使用这个注解所指明的运行器(runner)来运行测试,而不是JUnit默认的运行器

JUnit测试套件的使用,即批量运行测试类,以及JUnit中的参数化设置,接下来举例使用:

1.首先是新建两个测试任务类:

public class TaskTest1{  
    @Test  
    public void test(){  
        System.out.println("this is TaskTest1...");  
    }  
}  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
public class TaskTest2{  
    @Test  
    public void test() {  
        System.out.println("this is TaskTest2...");  
    }  
}  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

2.最后是新建一个套件类,包含以上两个任务类:

@RunWith(Suite.class)  
@Suite.SuiteClasses({TaskTest1.class,TaskTest2.class,TaskTest3.class})  
public class SuiteTest {  
    /* 
     * 1.测试套件就是组织测试类一起运行的 
     * 2.写一个作为测试套件的入口类,这个类里不包含其他的方法 
     * 3.更改测试运行器Suite.class 
     * 4.将要测试的类作为数组传入到Suite.SuiteClasses({})
     */  
}  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

JUnit4参数化设置的介绍和使用:

如果测试代码大同小异,代码结构都是相同的,不同的只是测试的数据和预期值,那么有没有更好的办法将相同的代码结构提取出来,提高代码的重用度呢?,那就要使用参数化测试了,以下是基本步骤:

1.要进行参数化测试,需要在类上面指定如下的运行器:@RunWith(Parameterized.class)
2.然后,在提供数据的方法上加上一个@Parameters注解,这个方法必须是静态static的,并且返回一个集合Collection
3.在测试类的构造方法中为各个参数赋值,(构造方法是由JUnit调用的),最后编写测试类,它会根据参数的组数来运行测试多次
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3
@RunWith(Parameterized.class) //1.更改默认的测试运行器为RunWith(Parameterized.class)  
public class ParameterTest{  

    //2.声明变量存放预期值和测试数据:
    int expected =0;  
    int input1 = 0;  
    int input2 = 0;  

    //3.声明一个返回值为Collection的公共静态方法,并使用@Parameters进行修饰:
    @Parameters  
    public static Collection<Object[]><object> data() {  
        return Arrays.asList(new Object[][]{  
                {3,1,2},  
                {4,2,2}  
        }) ;  
    }  

    //4.为测试类声明一个带有参数的公共构造函数,并在其中为之声明变量赋值:  
    public ParameterTest(int expected,int input1,int input2){  
        this.expected = expected;  
        this.input1 = input1;  
        this.input2 = input2;  
    }  

    //5.运行测试方法,即可完成对多组数据的测试:  
    @Test  
    public void testAdd(){  
        assertEquals(expected, new Calculate().add(input1, input2));  
    }    
}




一、环境搭建

       对于习惯使用Eclipse开发平台来说,Junit早已是非常通常的插件,在Eclipse开发平台中,可以非常方便地搭建Junit测试环境。

       1、在Eclipse上创建工程,任何Java工程都行。

       2、引入Junit的libraries库,选用Junit4。如下图所示:

3、新建一个Java类,用于演示Junit4类的自动生成,java代码如下:

  1. package com.hy;  
  2.   
  3. public class Demo {  
  4.   
  5.     public void method1() {  
  6.         System.out.println("method1");  
  7.     }  
  8.   
  9.     public void method2() {  
  10.         System.out.println("method2");  
  11.     }  
  12.   
  13.     public void method3() {  
  14.         System.out.println("method3");  
  15.     }  
  16.   
  17. }  

4、在该类上右键单击新建,选JUnit Test Case,自动生成一个对应的测试类,如下图所示:


4、这样就能自动地生成对应的测试类了,测试类代码发下:

[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. package com.hy;  
  2.   
  3. import static org.junit.Assert.*;  
  4.   
  5. import org.junit.After;  
  6. import org.junit.AfterClass;  
  7. import org.junit.Before;  
  8. import org.junit.BeforeClass;  
  9. import org.junit.Test;  
  10.   
  11. public class DemoTest {  
  12.   
  13.     @BeforeClass  
  14.     public static void setUpBeforeClass() throws Exception {  
  15.     }  
  16.   
  17.     @AfterClass  
  18.     public static void tearDownAfterClass() throws Exception {  
  19.     }  
  20.   
  21.     @Before  
  22.     public void setUp() throws Exception {  
  23.     }  
  24.   
  25.     @After  
  26.     public void tearDown() throws Exception {  
  27.     }  
  28.   
  29.     @Test  
  30.     public void testMethod1() {  
  31.         fail("Not yet implemented");  
  32.     }  
  33.   
  34.     @Test  
  35.     public void testMethod2() {  
  36.         fail("Not yet implemented");  
  37.     }  
  38.   
  39.     @Test  
  40.     public void testMethod3() {  
  41.         fail("Not yet implemented");  
  42.     }  
  43.   
  44. }  


5、如此一来,测试类环境的搭建过程就完成了,最后要做的就是,根据实际的业务需求,对测试类中的测试方法编写单元测试代码,直到运行调通。

 

二、基本规则

       从上面的演示可知,测试类名一般都以Test结尾,测试方法名以test开头。这个也是Junit的基本命名规则。

 

三、Junit注解

      我们此次针对的是Junit4版本,注解也是在Junit4版本才有的,之前的版本并无注解功能。而注解开发基本上被认为是一种优秀的设计,所以我们写单元测试用例时,尽可能地去了解并使用注解。

     @Test:使用该注解的方法为测试方法,自动运行时能够识别并被执行

      包含两个参数:expected=XXXException.class 期望出现的异常

                               timeout=xxx 设定程序运行的超时时间

     @Ignore:被忽略的测试方法

     @Before:在每个测试方法之前运行

     @After: 在每个测试方法之后运行

     @BeforeClass:在所有测试开始之前运行

     @AfterClass:在所有测试开始之后运行
  

      以上几个就是Junit 4的关键注解,熟练使用这几个注解,将来的测试用例编写肯定能事半功倍。

     注意:@Before与@BeforeClass的区别

     @Before会加在每个方法前执行,即有几个@Test就会执行几遍。

     @BeforeClass 只在所有测试之前执行,只会执行一次。并且@BeforeClass修饰的方法必须是公有的静态方法(public static )。

     @After和@AfterClass也类似

     每个测试类中这四个注解不能重复使用,一个方法只能从这四个注解中挑选其中一个。

 

四、基本写法

       1、setUp(),tearDown(),setUpBeforeClass(),tearDownAfterClass()这四个方法其实就是对应的@Before、@BeforeClass、@After、@AfterClass这四个注解,在Junit4开始使用注解时,其实可以替代这四个方法的功能,只是这四个方法是历史遗留方法,可以考虑使用,也可以直接使用注解替代。

       2、Assert是单元测试用例的核心,建议使用静态导入。

       3、待测试对象,一般建议设计成静态的。

       4、测试方法的要求:带@Test注解,方法名随意,返回值必须为void,不能带有参数,可以声明异常(可以参考演示代码)。

       5、Fixture方法的作用

            前面介绍的@Before、@BeforeClass、@After、@AfterClass注解修饰的方法,即为Fixture方法,它是在某些阶段必然被调用的方法,如注解功能所示。

            @Before、@After修饰方法的一个用处是对待测试对象的“复原”操作,如成员变量回归,数据库回滚等,目的是消除@Test方法之间的耦合。也可以用来打印日志。

            @BeforeClass修饰方法可以设计成用来加载一些耗时耗力的操作,如文件流的读取,数据库连接等,然后在@AfterClass中释放对应的资源即可。

      6、限时测试

           @Test(timeout=1000)超时时间单位为毫秒

           用于测试是否有死循环工是实时性要求比较高的用例,这个非常方便而且非常有用。

      7、测试异常

            @Test(expected=XXXException.class) XXXException为声明式异常

            用来验证声明式异常,注意此测试的含义:出现了期望的异常,叫做正常,若没出现异常,Junit会报错,认为不正常。这段描述有些拗口,请各位多琢磨琢磨。

      8、运行器Runner

            类注解@RunWith,指定不同的类可以改变测试类的行为

      9、参数化测试

            主要是针对一些相同功能却要进行多组参数测试的情况,开发步骤如下:

            1)参数化测试的类和普通测试类不同,要用特殊的Runner,类注解需要改为@RunWith(Parameterized.class)

            2)定义该测试类的成员变量,一个放测试参数,另一个放该参数产生的预期结果

            3)定义测试数据集合方法 public static Collection data() {...},注意该方法要用@Parameters修饰(数据格式为二维数组)

            4)定义带参数的构造函数,注意定义数据集合时,要和构造函数参数次序一致

            其他的与普通测试类似

            注意:若测试数据有两条,则该类下的所有@Test的方法都会执行两次,所以参数化测试的类不要和别的@Test放在一起。参数化测试方法一般建议单独建立类。

            演示代码如下:

[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. //指定@RunWith  
  2. @RunWith(Parameterized.class)  
  3. public class ParamTest {  
  4.   
  5.     //定义成员变量,i为测试参数,j为测试结果  
  6.     private int i;  
  7.     private int j;  
  8.   
  9.     //构造函数  
  10.     public ParamTest(int i, int j) {  
  11.         super();  
  12.         this.i = i;  
  13.         this.j = j;  
  14.     }  
  15.   
  16.     //测试数据集合,注意使用的注解,数据结构及次序  
  17.     @Parameters  
  18.     public static Collection data() {  
  19.         return Arrays.asList(new Object[][]{{1,2},{3,4},{4,6}});  
  20.     }  
  21.     @Test  
  22.     public void testMethod1() {  
  23.         System.out.println(i);  
  24.         System.out.println(j);  
  25.         //简单测试,只测试参数加1会不会等于预期结果  
  26.         Assert.assertEquals(i+1, j);  
  27.     }  
  28. }  

       预期的执行结果是前两组参数测试正确,最后一组测试错误,运行后的结果为:

执行结果与预期结果相符合,OK

 

      10、打包测试

            将测试类集中起来运行,提高测试效率,代码如下:

[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. @RunWith(Suite.class)  
  2. @Suite.SuiteClasses({  
  3.     DemoTest.class  
  4. })  
  5. public class ModuleTest {  
  6.   
  7.     public ModuleTest() {  
  8.         // TODO Auto-generated constructor stub  
  9.     }  
  10.   
  11. }  

           1)@Suite.SuiteClasses里面的是需要打包测试的类

           2)该类中可以为空,类名建议为模块名+Test结尾,如ModuleTest.java。

 

 

 

 

 

 

推荐阅读