通常我们要验证一个方法是否正常,需要用到多组测试用例,当然就算全部测试用例通过了,也不能说明这个方法没有 bug。
一、准备一个被测试类
public class Sample2 {
public int add(int numA, int numB) {
return numA + numB;
}
}
二、生成对应的测试类
public class Sample2Test {
private Sample2 _sample2;
@Before
public void setUp() throws Exception {
_sample2 = new Sample2();
}
@Test
public void add() throws Exception {
assertEquals(3, _sample2.add(1, 2));
}
}
三、增加批量测试用例的问题
如果通过如下手段,则会有点小问题。
@Test
public void add() throws Exception {
assertEquals(3, _sample2.add(1, 2));
assertEquals(4, _sample2.add(2, 2));
assertEquals(5, _sample2.add(3, 2));
assertNotEquals(6, _sample2.add(1, 2));
}
以上的写法的问题是这些测试用例不是纯粹的"单元",而是变成系列了,有先后关系了。整个测试过程只执行了一次 setUp 操作,所以说每个测试用例的环境是不一样的。
那么如何做到纯粹的单元测试呢?那就是每个方法每次执行只测一个用例,然后就执行 tearDown,当然我们不会每次执行完之后再去修改assertEquals(3, _sample2.add(1, 2));
中的参数,这样效率太低。
这个时候我们就可以通过参数化标注的手段来实现多组纯粹的单元测试。
四、参数化测试
先上完整代码
@RunWith(Parameterized.class)
public class Sample2Test {
private Sample2 _sample2;
int expected = 0;
int input1 = 0;
int input2 = 0;
@Parameterized.Parameters
public static java.util.Collection
完整的步骤如下
- 先修改 Junit 默认的测试运行器为参数化类,在测试类定义上一行添加
@RunWith(Parameterized.class)
- 生成一个静态的参数化数据工厂方法,操作如下
- 按 ctrl + N(CMD + M for Mac),选择
parameter method
,再选择Edit Template
,复制右侧的模板内容到测试类中.
- 填充所需要的测试用例
@Parameterized.Parameters
public static java.util.Collection
- 为测试类添加测试用例的字段
private Sample2 _sample2;
int expected = 0;
int input1 = 0;
int input2 = 0;
- 快捷键生成包含三个字段的构造器
public Sample2Test(int expected, int input1, int input2) {
this.expected = expected;
this.input1 = input1;
this.input2 = input2;
}
- 修改测试方法中的数字常量为字段
@Test
public void add() throws Exception {
assertEquals(expected, _sample2.add(input1, input2));
}
五、查看测试结果
结果如下如,可以看到左侧列表中有三个测试用例,并且都表示通过了。
六、小结
通过参数化测试,可以保证测试方法每次执行的之后只会测试一个测试用例,测试完成之后执行 tearDown 做清理工作,保证每个测试用例不会相互影响。
实现的逻辑是参数化运行器每次读取一组数据的时候都会重新通过传入数据组给测试类构造器,从而创建一个新对象,然后执行 setUp、testYourMethod、tearDown 操作。