JUnit单元测试学习摘要教程

本文详细介绍如何使用JUnit4进行单元测试,包括创建测试环境、编写测试用例及参数化测试等。并通过实例演示如何对一个计算器类进行各种功能的单元测试。

1.教程摘要

  在编写代码的时候通过System.out和alert来做测试,非常麻烦,而且不够正规,对于即将步入工作的人来说,一个正规的写代码习惯和测试习惯是非常重要的,因此应当认真学学如何使用JUnit。  

  junit包有junit3和junit4两个版本,一般都使用junit4这个版本,兼容性好且更灵活。

2.教程实例

步骤1:创建待测试类

首先新建一个项目叫JUnit_Test,我们编写一个Calculator类,这是一个能够简单实现加减乘除、平方、开方的计算器类,然后对这些功能进行单元测试。这个类并不是很完美,我们故意保留了一些Bug用于演示,这些Bug在注释中都有说明。该类代码如下:

package dyz.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;
    }
}

步骤2:在eclipse中为项目添加JUnit环境

右键JUnit_Test项目,在build path中“add library”,添加JUnit,如下图所示:

步骤3:创建测试类

右键Calculator类,选择“new",创建JUnit Test Case

步骤4:编写测试用例代码

测试用例代码如下:

package dyz.calculatortest;
import static org.junit.Assert.*;

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

import xw.calculator.Calculator;

public class CalculatorTest {
    private static Calculator calculator = new Calculator();

    // 复原操作,表明对每个Test方法测试以后都会进行这个方法操作。
    @Before
    public void setUp() throws Exception {
        calculator.clear();// 结果清零
    }

    @Test
    public void testAdd() {
        // fail("Not yet implemented");
        calculator.add(2);
        calculator.add(3);
        assertEquals(5, calculator.getResult());
    }

    @Test
    public void testSubstract() {
        // fail("Not yet implemented");
        calculator.add(10);
        calculator.substract(2);
        assertEquals(8, calculator.getResult());
    }

    // 忽略标注,表明这个方法功能还没有实现
    @Ignore("Multiply() Not yet implemented")
    @Test
    public void testMultiply() {
        fail("Not yet implemented");
    }

    @Test
    public void testDivide() {
        // fail("Not yet implemented");
        calculator.add(8);
        calculator.divide(2);
        assertEquals(4, calculator.getResult());
    }

    // Timeout参数表明了你要设定的时间,单位为毫秒,因此1000就代表1秒。
    @Test(timeout = 1000)
    public void squareRoot() {
        calculator.squareRoot(4);
        assertEquals(2, calculator.getResult());

    }

    /**
     * square1/square2/square3分别用来测试正数,0,复数的平方
     */
    @Test
    public void square1() {
        calculator.square(2);
        assertEquals(4, calculator.getResult());
    }

    @Test
    public void square2() {
        calculator.square(0);
        assertEquals(0, calculator.getResult());
    }

    @Test
    public void square3() {
        calculator.square(-3);
        assertEquals(9, calculator.getResult());
    }
}

常用注解说明  

  1、@BeforeClass所修饰的方法在所有方法加载前执行,而且他是静态的在类加载后就会执行该方法,

在内存中只有一份实例,适合用来加载配置文件。

  2、@AfterClass所修饰的方法在所有方法执行完毕之后执行,通常用来进行资源清理,例如关闭数据库连接。

  3、@Before和@After在每个测试方法执行前都会执行一次。

       4、@Test(excepted=XX.class) 在运行时忽略某个异常。

  5、@Test(timeout=毫秒) 允许程序运行的时间。

  6、@Ignore 所修饰的方法被测试器忽略。

  7、@RunWith 可以修改测试运行器 org.junit.runner.Runner

 

3.参数化测试与运行器(Runner)

考虑一种场景,如果要单独测试正数的平方,0的平方以及负数的平方,那么就要创建三个测试方法来进行测试,这样会显得特别繁琐,如步骤4中最后的三个测试方法square1()、square2()和square3()。JUnit考虑到了这种情况,提出了参数化测试方法。这个时候运行器也不是默认的运行器,而是通过@RunWith(Parameterized.class)来标注。

参数化测试代码如下所示;

package dyz.calculatortest;
import static org.junit.Assert.*;
import java.util.Arrays;
import java.util.Collection;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import dyz.calculator.Calculator;
@RunWith(Parameterized.class)
public class SquareTest {
    private static Calculator calculator = new Calculator();
    private int param;
    private int result;

    @Parameters
    public static Collection<Object[]> data() {//定义测试数据的集合
        return Arrays.asList(new Object[][] { { 2, 4 }, { 0, 0 }, { -3, 9 }});
    }

    // 构造函数,对变量进行初始化,参数的顺序与数据集成的顺序相关
    public SquareTest(int param, int result) {
        this.param = param;
        this.result = result;
    }

    // 复原操作,表明对每个Test方法测试以后都会进行这个方法操作。
    @Before
    public void setUp() throws Exception {
        calculator.clear();// 结果清零
    }

    @Test
    public void testSquare() {
        calculator.square(param);
        assertEquals(result, calculator.getResult());
    }
}

具体步骤:

  1、更改默认的测试运行器为@RunWith(Parameterized.class)。

  2、声明变量来存放预期值和测试值。

  3、声明一个返回值为Collection的公共静态方法,并用@Parameters修饰。

  4、为测试类声明一个带有参数的公共构造函数,并在其中为他声明变量赋值。

 

4.打包测试

考虑另外一种场景,如果一个项目中有许多个测试类,一个一个去运行会非常繁琐,这个时候就可以考虑使用打包测试。将所有需要运行的测试类集中起来,一次性的运行完毕,大大的方便了我们的测试工作。

右键Calculator类,新建一个JUnit Test Suite,如下图所示。

然后选择需要打包测试的测试类,如下图所示:

打包测试类叫做AllTests,需要打包测试的三个测试类是CalculatorTest,SquareTest和test。点击Finish完成打包测试,生成的打包测试类代码如下:

package dyz.calculatortest;

import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;

@RunWith(Suite.class)
@SuiteClasses({SquareTest.class,CalculatorTest.class,Test.class})
public class AllTests {

}

运行结果如下:

注意事项:

  1、作为测试套件的入口类,类中不能包含任何方法。

  2、更改测试运行器Suite.class。

  3、将需要运行的测试类放入Suite.SuiteClasses({})的数组中。

转载于:https://my.oschina.net/fairy1674/blog/795714

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值