zoukankan      html  css  js  c++  java
  • Junit使用教程

    Junit是Java的单元测试工具,同时也是极限编程的好帮手。Junit4借助于Java5的Annotation(标注类)和静态导入的新特性,与Junit3有很大的区别,所以建议初学者直接使用Junit4。

    构建项目

    虽然Junit早已成为Eclipse的标配,但我还是习惯使用Maven构建项目,我使用Junit版本是4.11,构建的项目JunitDemo构架如下图:

    在src/main/java我们新建一个计算器类(Calculator),以待测试,Calculator.java代码如下:

    package net.oseye;
    
    public class Calculator {
    	/**
    	 * 加法
    	 * @param x
    	 * @param y
    	 * @return
    	 */
    	public int addition(int x,int y){
    		return x+y;
    	} 
    	/**
    	 * 减法
    	 * @param x
    	 * @param y
    	 * @return
    	 */
    	public int subtraction(int x,int y){
    		return x-y;
    	} 
    	/**
    	 * 乘法
    	 * @param x
    	 * @param y
    	 * @return
    	 */
    	public int multiplication(int x,int y){
    		return x*y;
    	} 
    }


    添加测试类

    使用Eclipse添加测试类也是非常方便的,在src/test/java右键->New->Junit Test Case,在对话框中填写名称和选择待测试类:

    点击 Next,可以选择待测试的方法:

    我们选择了addition方法,生成的测试类CalculatorTest.java代码:

    package net.oseye;
    
    import static org.junit.Assert.*;
    
    import org.junit.Test;
    
    public class CalculatorTest {
    
    	@Test
    	public void testAddition() {
    		fail("Not yet implemented");
    	}
    }

    生成默认的测试使用fail,所以运行总会是失败的。


    运行测试

    在CalculatorTest.java上右键(或Ctrl+F11),运行测试用例:


    @Test

    每个单元测试用例都会以@Test标注,而@Test有三种方式:断言测试、异常测试和超时测试。

    1. 断言测试:
      package net.oseye;
      
      import static org.junit.Assert.*;
      
      import org.junit.Test;
      
      public class CalculatorTest {
      
      	@Test
      	public void testAddition() {
      		Calculator c=new Calculator();
      		assertEquals(5, c.addition(2, 3));
      	}
      }
      Junit有很多断言测试方法,如
      void assertEquals(long expected, long actual)
      实际值和期望值相同就pass,否则就fail。
    2. 异常测试
      package net.oseye;
      
      import static org.junit.Assert.*;
      
      import org.junit.Test;
      
      public class CalculatorTest {
      
      	@Test(expected=RuntimeException.class)
      	public void testAddition() {
      		Calculator c=new Calculator();
      		assertEquals(5, c.addition(2, 3));
      	}
      }
      如果没有抛出异常或抛出不同的异常,则测试失败。
    3. 超时测试
      package net.oseye;
      
      import static org.junit.Assert.*;
      
      import org.junit.Test;
      
      public class CalculatorTest {
      
      	@Test(timeout=1000)
      	public void testAddition() {
      		Calculator c=new Calculator();
      		assertEquals(5, c.addition(2, 3));
      	}
      }
      timeout单位是毫秒,示例表示如果运行测试用例超过1000毫秒就失败。


    @Before和
    @After

    我上面的例子中测试方法中是要先New一个Calculator实例,如果成千上百个测试用例,我都要做一些重复准备资源代码,如New示例、I/O对文件,创建数据库连接等等,那是比较麻烦而且无意义。

    Junit为我们提供了@Before和@After标注,每个测试方法执行前执行@Before标注的方法,每个测试方法执行后执行@After标注的方法,@After可以清理现场:

    package net.oseye;
    
    import static org.junit.Assert.*;
    
    import org.junit.After;
    import org.junit.Before;
    import org.junit.Test;
    
    public class CalculatorTest {
    	private Calculator c=null;
    	
    	@Before
    	public void init(){
    		System.out.println("@Before");
    		c=new Calculator();
    	}
    	
    	@Test
    	public void testAddition() {
    		assertEquals(5, c.addition(2, 3));
    	}
    	@Test
    	public void testAddition2() {
    		assertEquals(8, c.addition(5, 3));
    	}
    	
    	@After
    	public void destroy(){
    		System.out.println("@After");
    		c=null;
    	}
    }

    运行结果:

    @Before
    @After
    @Before
    @After

    示例的@After我只是销毁了c,其实这里意义不大,但比如要清理由于测试二导致的垃圾数据,就很有必要了。


    @BeforeClass和@AfterClass

    @Before和@After在每次执行测试方法时都会执行,这对于进行I/O操作等又比较耗资源,所以Junit又提供了@BeforeClass和@AfterClass标注,是在测试类之前和之后执行,@BeforeClass和@AfterClass必须是static类型的:

    package net.oseye;
    
    import static org.junit.Assert.*;
    
    import org.junit.After;
    import org.junit.AfterClass;
    import org.junit.Before;
    import org.junit.BeforeClass;
    import org.junit.Test;
    
    public class CalculatorTest {
    	private static Calculator c=null;
    	
    	@BeforeClass
    	public static void init(){
    		System.out.println("@BeforeClass");
    		c=new Calculator();
    	}
    	
    	@Test
    	public void testAddition() {
    		assertEquals(5, c.addition(2, 3));
    	}
    	@Test
    	public void testAddition2() {
    		assertEquals(8, c.addition(5, 3));
    	}
    	
    	@AfterClass
    	public static void destroy(){
    		System.out.println("@AfterClass");
    		c=null;
    	}
    }

    输出:

    @BeforeClass
    @AfterClass


    测试运行器Runner

    这里先说下测试运行器,为后面的参数化测试和套件测试做个铺垫。

    测试运行期Runner是JUnit中负责执行测试方法的类,JUnit为提供了默认的测试运行器,但是没有要求你必须使用默认运行器,因此你可以定制自己的测试运行器。

    定制自己的测试运行器必须继承自abstract类org.junit.runner.Runner,然后使用@Runwith(定制的运行器.class)来指定测试使用自己的定制运行器,定制这部分可以自己尝试下,暂时不深入。


    测试套件Suite

    什么是测试套件?其实就是把各个测试组装在一起测试,JUnit4的测试套件反而没有JUnit3的测试套件直观,而是要使用定制的测试运行器和指定测试类,步骤是这样的:

    1. 创建一个空类作为测试套件的入口;
    2. 使用Suite运行器代替默认运行器;
    3. 将需要测试的类组成数组作为@SuiteClasses 的参数,以@SuiteClasses标注测试套件类;

    注意:这个空类必须使用public 修饰符,而且存在public 的无参构造函数(类的默认构造函数即可)。

    再添加一个测试类,用来测试减法CalculatorTest2.java:

    package net.oseye;
    
    import static org.junit.Assert.*;
    
    import org.junit.AfterClass;
    import org.junit.BeforeClass;
    import org.junit.Test;
    
    public class CalculatorTest2 {
    	private static Calculator c=null;
    	
    	@BeforeClass
    	public static void init(){
    		System.out.println("@BeforeClass");
    		c=new Calculator();
    	}
    	
    	@Test
    	public void testSubtraction() {
    		assertEquals(7, c.subtraction(10, 3));
    	}
    	@Test
    	public void testSubtraction2() {
    		assertEquals(5, c.subtraction(20, 15));
    	}
    	
    	@AfterClass
    	public static void destroy(){
    		System.out.println("@AfterClass");
    		c=null;
    	}
    }

    生成的AllTests.java代码如下:

    package net.oseye;
    
    import org.junit.runner.RunWith;
    import org.junit.runners.Suite;
    import org.junit.runners.Suite.SuiteClasses;
    
    @RunWith(Suite.class)
    @SuiteClasses({ CalculatorTest.class, CalculatorTest2.class })
    public class AllTests {
    
    }

    Eclipse已经为你添加了标注,省了好多事。运行输出:

    @BeforeClass
    @AfterClass
    @BeforeClass
    @AfterClass


    参数化测试

    我们看到CalculatorTest测试类中用了两个测试用例2+3=5和5+3=8,但对于一个方法的测试可能有成千上百个测试用例,如果每个测试用例都要用一个测试方法的话那我们就惨了!

    因此JUnit又为你准备了参数化测试方法,编码步骤:

    1. 对于测试类使用Parameterized运行器代替默认运行器;
    2. 创建一个静态(static)测试数据供给(feed)方法,其返回类型为Collection,并用@Parameter 注释以修饰;Collection就是输入参数和期望值;
    3. 通过构造函数把Collection的值传入测试类;
    4. 编写测试方法;

    仍使用CalculatorTest测试类,代码如下:

    package net.oseye;
    
    import static org.junit.Assert.*;
    
    import java.util.Arrays;
    import java.util.Collection;
    
    import org.junit.AfterClass;
    import org.junit.BeforeClass;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.junit.runners.Parameterized;
    import org.junit.runners.Parameterized.Parameters;
    
    @RunWith(Parameterized.class)
    public class CalculatorTest {
    	private static Calculator c=null;
    	
    	private int expected;
    	private int x;
    	private int y;
    	public CalculatorTest(int expected,int x,int y){
    		this.expected=expected;
    		this.x=x;
    		this.y=y;
    	}
    	
    	@BeforeClass
    	public static void init(){
    		System.out.println("@BeforeClass");
    		c=new Calculator();
    	}
    	
    	@Test
    	public void testAddition() {
    		assertEquals(this.expected, c.addition(this.x, this.y));
    	}
    	
    	@AfterClass
    	public static void destroy(){
    		System.out.println("@AfterClass");
    		c=null;
    	}
    	
    	@Parameters
    	public static Collection<Object[]> data(){
    		return Arrays.asList(new Object[][]{
    				{5,2,3},
    				{11,8,3},
    				{12,8,4}
    		});
    	}
    }
    出处:http://www.zhaiqianfeng.com    
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    Javascript语言精粹之String常用方法分析
    Javascript语言精粹之Array常用方法分析
    Javascript语言精粹之正则表达式知识整理
    深入浅出KnockoutJS
    用KnockoutJS实现ToDoMVC代码分析
    用JavaScript实现网页动态水印
    LINQ to JavaScript 源码分析
    《Javascript高级程序设计》读书笔记之bind函数详解
    《Javascript高级程序设计》读书笔记之闭包
    转载-MySQL 加锁处理分析
  • 原文地址:https://www.cnblogs.com/zhaiqianfeng/p/4620161.html
Copyright © 2011-2022 走看看