Junit4入门

来源:互联网 发布:安邦 知乎 编辑:程序博客网 时间:2024/06/05 04:00

Junit4入门

简介:

JUnit是一个Java语言的单元测试框架。它由Kent Beck和Erich Gamma建立,逐渐成为源于Kent Beck的sUnit的xUnit家族中最为成功的一个。 JUnit有它自己的JUnit扩展生态圈。多数Java的开发环境都已经集成了JUnit作为单元测试的工具。

JUnit是由 Erich Gamma 和 Kent Beck 编写的一个回归测试框架(regression testing framework)。Junit测试是程序员测试,即所谓白盒测试,因为程序员知道被测试的软件如何(How)完成功能和完成什么样(What)的功能。Junit是一套框架,继承TestCase类,就可以用Junit进行自动测试了。

入门实例:

先创建一个测试类Calculator

public class Calculator {    private static int result; // 静态变量,用于存储运行结果    public void add(int n) {        result = result + n;    }    public void substract(int n) {        result = result - 1;  //Bug: 正确的应该是 result =result-n    }    public void multiply(int n) {    }         // 此方法尚未写好    public void divide(int n) {        result = result / n;    }    public void square(int n) {        result = n * n;    }    public void squareRoot(int n) {        for (; ;) ;            //Bug : 死循环    }    public void clear() {     // 将结果清零        result = 0;    }    public int getResult() {        return result;    }}

然后在Calculator类右键new里面选择JUnit Test Case

生成CalculatorTest类

public class CalculatorTest { private static Calculator calculator = new Calculator();@Beforepublic void setUp() throws Exception {calculator.clear();//复原操作,不被其他结果影响}@Testpublic void testAdd() {calculator.add(5);calculator.add(1); assertEquals(6, calculator.getResult());//将预计结果与实际结果进行对比}@Testpublic void testSubstract() {  calculator.add(10);                assertEquals(9, calculator.getResult());}@Testpublic void testMultiply() {fail("Not yet implemented");}@Testpublic void testDivide() {  calculator.add(8);        calculator.divide(2);        assertEquals(4, calculator.getResult());}}

Junit的运行流程

可以定义一个类TestFlow

public class TestFlow {@BeforeClasspublic static void setUpBeforeClass() throws Exception {System.out.println("BeforeClass...");}@AfterClasspublic static void tearDownAfterClass() throws Exception {System.out.println("AfterClass...");}@Beforepublic void setUp() throws Exception {System.out.println("Before...");}@Afterpublic void tearDown() throws Exception {System.out.println("After...");}@Testpublic void test1() {System.out.println("test1");}@Testpublic void test2() {System.out.println("test2");}}

输出:

BeforeClass...Before...test2After...Before...test1After...AfterClass...

可以看出,beforeclass和afterclass在整个运行流程就在开头和结尾执行,但是before和after会在每个测试方法执行前后执行

Junit基本注解

@BeforeClass注解

被@BeforeClass注解的方法会是: 只被执行一次 运行junit测试类时第一个被执行的方法 这样的方法被用作执行计算代价很大的任务,如打开数据库连接。被@BeforeClass 注解的方法应该是静态的(即 static类型的).

@AfterClass注解

被@AfterClass注解的方法应是: 只被执行一次 运行junit测试类是最后一个被执行的方法 该类型的方法被用作执行类似关闭数据库连接的任务。被@AfterClass 注解的方法应该是静态的(即 static类型的).

@Before注解

被@Before 注解的方法应是: junit测试类中的任意一个测试方法执行 前 都会执行此方法 该类型的方法可以被用来为测试方法初始化所需的资源。

@After注解

被@After注解的方法应是: junit测试类中的任意一个测试方法执行后 都会执行此方法, 即使被@Test 或 @Before修饰的测试方法抛出异常 该类型的方法被用来关闭由@Before注解修饰的测试方法打开的资源。

@Test 注解

被@Test注解的测试方法包含了真正的测试代码,并且会被Junit应用为要测试的方法。@Test注解有两个可选的参数: expected 表示此测试方法执行后应该抛出的异常,(值是异常名) timeout 检测测试方法的执行时间

JUnit测试套件使用及参数化设置

JUnit测试套件 如果在测试类不端增加的情况下,如何运行所有的单元测试代码类?一个个测试类的执行吗?显然繁琐且费劲。 将要运行的测试类集成在我们的测试套件中,比如一个系统功能对应一个测试套件,一个测试套件中包含多个测试类,每次测试系统功能时,只要执行一次测试套件就可以了。

如下三个测试类要一起测试

public class Task01Test {@Testpublic void test() {System.out.println("Task01Test.test()");}}public class Task02Test {@Testpublic void test() {System.out.println("Task02Test.test()");}}public class Task03Test {@Testpublic void test() {System.out.println("Task03Test.test()");}}

可以新建一个套件类,包含以上三个任务类:

import org.junit.runner.RunWith;import org.junit.runners.Suite;  @RunWith(Suite.class)  @Suite.SuiteClasses({Task01Test.class,Task02Test.class,Task03Test.class})  public class SuiteTest {  /*      * 1.测试套件就是组织测试类一起运行的      *       * 写一个作为测试套件的入口类,这个类里不包含其他的方法      * 更改测试运行器Suite.class      * 将要测试的类作为数组传入到Suite.SuiteClasses({})      */  }

①使用@RunWith注解,修改测试运行器。例如@RunWith(Suite.class),这个类就成为测试套件的入口类。

②@Suite.SuiteClasses()中放入测试套件的测试类,以数组的形式{class1,class2,......}作为参数

JUnit参数化设置

如果测试代码大同小异,代码结构都是相同的,不同的只是测试的数据和预期值,那么有没有更好的办法将相同的代码结构提取出来,提高代码的重用度呢? 解决:进行参数化测试。 步骤:

①要进行参数化测试,需要在类上面指定如下的运行器:@RunWith (Parameterized.class)

②然后,在提供数据的方法上加上一个@Parameters注解,这个方法必须是静态static的,并且返回一个集合Collection。

③在测试类的构造方法中为各个参数赋值,(构造方法是由JUnit调用的),最后编写测试类,它会根据参数的组数来运行测试多次。

import static org.junit.Assert.*;import java.util.Arrays;import java.util.Collection;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 ParameterTest {  int expected =0;      int input1 = 0;      int input2 = 0;            //3.声明一个返回值 为Collection的公共静态方法,并使用@Parameters进行修饰      @Parameters      public static Collection<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;      }            @Test    public void  testadd(){     assertEquals(expected, new Calcul().add(input1, input2));      }}