您的位置:首页 > 其它

学习使用JUnit4进行单元测试

2017-06-10 01:19 246 查看
借用http://blog.csdn.net/andycpp/article/details/1327147等文章上面的例子和教程进行学习总结,自己敲了一遍代码,发现里面有些东西,可能版本原因,已经稍微改了,不过原理还是相似的。

1、新建一个Maven Project,在pom.xml中添加JUnit4引用:


<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion>
<groupId>com.test</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>

<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>

2、新建一个实现加减乘除、平方、开方的计算器类,然后对这些功能进行单元测试,这个类故意保留了一些Bug用于演示。


package jlc;

public class Calculator {
// 静态变量,用于存储运行结果
private static int result;

public void add(int n) {
result = result + n;
}

public void substract(int n) {
// Bug: 正确的应该是 result =result-n
result = result - 1;
}

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) {
// Bug : 死循环
for (;;)
;
}

public void clear() {
// 将结果清零
result = 0;
}

public int getResult() {
return result;
}
}


3、默认情况下的测试

右键点击类Calculator弹出菜单,选择“New -> Other -> Junit -> JUnit Test Case”,默认下一步...生成一个包含空的 

测试用例的类CalculatorTest,测试用例可以修改。

修改后如下:

package jlc;

import static org.junit.Assert.*;

import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.BlockJUnit4ClassRunner;

//使用了系统默认的BlockJUnit4ClassRunner,可不用写
@RunWith(BlockJUnit4ClassRunner.class)
public class CalculatorTest {

private static Calculator calculator = new Calculator();

//执行顺序:@BeforeClass,@Before,@Test,@After,@AfterClass

//在本类加载前执行,只执行一次。注意有关键字:static
@BeforeClass
public static void testBeforeClass() {
System.out.println("public static void testBeforeClass()");
}
//在本类加载后执行,只执行一次。注意有关键字:static
@AfterClass
public static void testAfterClass() {
System.out.println("public static void testAfterClass()");
}

//在任何一个测试方法执行之前执行,一个测试类只有一个@Before和@After
@Before
public void testBefore() {
System.out.println("public void testBefore()");
calculator.clear();
}

//在任何一个测试执行方法之后执行
@After
public void testAfter() {
System.out.println("public void testAfter()");
}

//表明这是一个测试方法,名字没限制,返回值必须是void,多个@Test不是顺序执行的
@Test
public void testAdd() {
System.out.println("开始求和...");
calculator.add(2);
calculator.add(3);
//判断期待结果和实际结果是否相等
assertEquals(5, calculator.getResult());
}

@Test
public void testSubstract() {
System.out.println("开始相减...");
calculator.add(10);
calculator.substract(2);
assertEquals(8, calculator.getResult());
}

@Ignore("忽略测试某些尚未完成的方法")
@Test
public void testMultiply() {
}

@Test
public void testDivide() {
System.out.println("开始相除...");
calculator.add(8);
calculator.divide(2);
assertEquals(4, calculator.getResult());
}

//限时测试,因为一些方法可能有死循环等情况
@Test(timeout = 1000 )
public void testSquareRoot() {
System.out.println("开始求平方根...");
calculator.squareRoot( 4 );
assertEquals( 2 , calculator.getResult());
}

//异常测试
@Test(expected = ArithmeticException.class)
public void divideByZero() {
System.out.println("开始除0...");
calculator.divide(0);
}
}

一些说明(也可以看上面代码注释):

(1)JUnit运行时都是由一个runner运行的,可以根据需要选择不同的Runner来运行测试代码。指定一个Runner,需要使用 

@RunWith标注,并且把所指定的Runner作为参数传递给它。系统自动使用默认Runner BlockJUnit4ClassRunner来运行代码。

(2)执行顺序:@BeforeClass,@Before,@Test,@After,@AfterClass

右键点击测试类CalculatorTest弹出菜单,选择“Run As -> JUnit Test”,运行结果的【JUnit】栏如下:



【Console】栏输出如下,可对照查看标注的执行顺序:

4、参数化测试,写一个测试函数,把这若干种情况作为参数传递进去,一次性的完成测试。

首先,要为这种测试专门生成一个新的类,为这个类指定一个Runner,特殊的功能要用特殊的Runner:@RunWith(Parameterized.class) 

第二,定义测试数据的集合,也就是上述的data()方法,该方法可以任意命名,但是必须使用@Parameters标注进行修饰。这是一个二维数组,每组数据产生一个测试Instance.

第三,构造函数,取得传过来的参数。

最后,用取得的参数做测试。

新建测试类ParameterizedTest:

package jlc;

import static org.junit.Assert.*;

import java.util.Arrays;
import java.util.Collection;
import java.util.List;

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 ParameterizedTest {
private static Calculator calculator = new Calculator();

private int param;
private int result;

@Parameters
public static List<Integer[]> data() {
return Arrays.asList(new Integer[][] { { 2, 4 }, { 0, 0 }, { -3, 9 }, });
}

// 构造函数,对变量进行初始化
public ParameterizedTest(int param, int result) {
this.param = param;
this.result = result;
}

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

}
}

测试结果如下,成功通过:



5、打包测试,一次把所有测试跑一遍。

这个功能也需要使用一个特殊的 Runner ,因此需要向 @RunWith 标注传递一个参数 Suite.class 。同时,还需要另外一个标注 @Suite.SuiteClasses ,来表明这个类是一个打包测试类,把需要打包的类作为参数传递给该标注就可以了。

新建测试类SuiteTest:

package jlc;

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

//用来执行分布在多个类中的测试用例
@RunWith(Suite.class)
@Suite.SuiteClasses({ CalculatorTest.class, ParameterizedTest.class })
public class SuiteTest {

}

运行结果如下:



 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: