通常我們要驗(yàn)證一個(gè)方法是否正常,需要用到多組測(cè)試用例,當(dāng)然就算全部測(cè)試用例通過了,也不能說明這個(gè)方法沒有 bug。
一、準(zhǔn)備一個(gè)被測(cè)試類
public class Sample2 {
public int add(int numA, int numB) {
return numA + numB;
}
}
二、生成對(duì)應(yīng)的測(cè)試類
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));
}
}
三、增加批量測(cè)試用例的問題
如果通過如下手段,則會(huì)有點(diǎn)小問題。
@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));
}
以上的寫法的問題是這些測(cè)試用例不是純粹的"單元",而是變成系列了,有先后關(guān)系了。整個(gè)測(cè)試過程只執(zhí)行了一次 setUp 操作,所以說每個(gè)測(cè)試用例的環(huán)境是不一樣的。
那么如何做到純粹的單元測(cè)試呢?那就是每個(gè)方法每次執(zhí)行只測(cè)一個(gè)用例,然后就執(zhí)行 tearDown,當(dāng)然我們不會(huì)每次執(zhí)行完之后再去修改assertEquals(3, _sample2.add(1, 2));中的參數(shù),這樣效率太低。
這個(gè)時(shí)候我們就可以通過參數(shù)化標(biāo)注的手段來實(shí)現(xiàn)多組純粹的單元測(cè)試。
四、參數(shù)化測(cè)試
先上完整代碼
@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<Object[]> data() {
return Arrays.asList(new Object[][]{
{3, 1, 2},
{4, 2, 2},
{0, -2, 2}
});
}
public Sample2Test(int expected, int input1, int input2) {
this.expected = expected;
this.input1 = input1;
this.input2 = input2;
}
@Before
public void setUp() throws Exception {
_sample2 = new Sample2();
}
@Test
public void add() throws Exception {
assertEquals(expected, _sample2.add(input1, input2));
}
}
完整的步驟如下
- 先修改 Junit 默認(rèn)的測(cè)試運(yùn)行器為參數(shù)化類,在測(cè)試類定義上一行添加
@RunWith(Parameterized.class) - 生成一個(gè)靜態(tài)的參數(shù)化數(shù)據(jù)工廠方法,操作如下
- 按 ctrl + N(CMD + M for Mac),選擇
parameter method,再選擇Edit Template,復(fù)制右側(cè)的模板內(nèi)容到測(cè)試類中.
Snip20180403_11.png
Snip20180403_12.png - 填充所需要的測(cè)試用例
@Parameterized.Parameters
public static java.util.Collection<Object[]> data() {
return Arrays.asList(new Object[][]{
{3, 1, 2},
{4, 2, 2},
{0, -2, 2}
});
}
- 為測(cè)試類添加測(cè)試用例的字段
private Sample2 _sample2;
int expected = 0;
int input1 = 0;
int input2 = 0;
- 快捷鍵生成包含三個(gè)字段的構(gòu)造器
public Sample2Test(int expected, int input1, int input2) {
this.expected = expected;
this.input1 = input1;
this.input2 = input2;
}
- 修改測(cè)試方法中的數(shù)字常量為字段
@Test
public void add() throws Exception {
assertEquals(expected, _sample2.add(input1, input2));
}
五、查看測(cè)試結(jié)果
結(jié)果如下如,可以看到左側(cè)列表中有三個(gè)測(cè)試用例,并且都表示通過了。

六、小結(jié)
通過參數(shù)化測(cè)試,可以保證測(cè)試方法每次執(zhí)行的之后只會(huì)測(cè)試一個(gè)測(cè)試用例,測(cè)試完成之后執(zhí)行 tearDown 做清理工作,保證每個(gè)測(cè)試用例不會(huì)相互影響。
實(shí)現(xiàn)的邏輯是參數(shù)化運(yùn)行器每次讀取一組數(shù)據(jù)的時(shí)候都會(huì)重新通過傳入數(shù)據(jù)組給測(cè)試類構(gòu)造器,從而創(chuàng)建一個(gè)新對(duì)象,然后執(zhí)行 setUp、testYourMethod、tearDown 操作。

