該內容爲“中國大學MOOC”,華中科技大學《軟件測試與質量》第8周單元測試部分的筆記。
IDEA工具可進官網下載,這裏使用的2019.3.2版本。
BMI計算程序
新建工程,命名爲“HealthIndex”:
在src目錄下新建package,“sample.ut”:
在建好的包下新建class,“BMI”:
BMI.java中包含的內容有:
1. 定義屬性
private double weight; // 體重
private double height; // 身高
2. getter&setter
在空白處右鍵,選擇“Gennerate”,然後選擇“Getter and Setter”:
會自動生成下述方法:
public double getWeight() {
return weight;
}
public void setWeight(double weight) {
this.weight = weight;
}
public double getHeight() {
return height;
}
public void setHeight(double height) {
this.height = height;
}
3. 同時設定所有屬性
public void setParams(double w, double h){
this.weight = w;
this.height = h;
}
4. 定義構造方法
public BMI(double w, double h){
this.weight = w;
this.height = h;
}
5. 定義功能方法
public String getBMIType(){
// 1. 初始化
String result = "";
double bmi = 0.0;
if(weight>0 && height>0){
// 2. 計算BMI
bmi = weight / (height*height);
// 3. 判斷所屬分類
if(bmi<20.5){
result = "偏瘦";
}else if(bmi<24){
result = "正常";
}else if(bmi<28){
result = "偏胖";
}else{
result = "肥胖";
}
}else{
result = "數據有誤";
}
// 4. 返回分類結果
return result;
}
使用Junit4創建簡單測試方法
創建一個新的文件夾“test”,跟src同層:
右鍵test文件夾,把它標記爲Test Sources Root:
在test文件夾下也建立同名的包“sample.ut”:
回到BMI.java文件中,在空白處右鍵,選擇“Go To” --> “Test”:
創建新的Test:
選擇“JUnit4”,勾選下圖所示部分:
如果提示沒有JUnit4包,點擊右邊的“Fix”:
在彈出的框中直接點OK即可:
如果導入失敗,在導入過程中檢查該路徑:
發現路徑下沒有jar包:
可以到IDEA的下載路徑的lib文件夾下找到,並copy過來:
創建成功後,在BMITest.java中定義被測對象,並補充測試方法:
BMI testObj;
@Test
public void getBMIType() {
// 創建被測對象
testObj = new BMI(45.0, 1.6);
// 調用測試方法
String actual = testObj.getBMIType();
// 校驗測試結果
String except = "偏瘦";
assertTrue(actual==except);
}
完整的BMITest.java內容爲:
package sample.ut;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.*;
public class BMITest {
BMI testObj;
@Before
public void setUp() throws Exception {
}
@After
public void tearDown() throws Exception {
}
@Test
public void getBMIType() {
// 創建被測對象
testObj = new BMI(45.0, 1.6);
// 調用測試方法
String actual = testObj.getBMIType();
// 校驗測試結果
String except = "偏瘦";
assertTrue(actual==except);
// 銷燬測試對象
testObj = null;
}
}
點擊方法前的運行:
測試通過:
修改expect,使其失敗,再次運行:
運行失敗,可通過控制檯查看出錯原因。
一次性執行多個測試方法
在上述BMITest.java中,可定義多個測試方法@Test進行測試:
@Test
public void getBMIType1() {
testObj = new BMI(45.0, 1.6);
String actual = testObj.getBMIType();
String except = "偏瘦";
assertTrue(actual==except);
testObj = null;
}
@Test
public void getBMIType2() {
testObj = new BMI(55.0, 1.6);
String actual = testObj.getBMIType();
String except = "正常";
assertTrue(actual==except);
testObj = null;
}
需要注意的是,執行測試的順序和定義測試的順序不一定相同,且這樣寫測試方法會造成冗餘。
Junit4提供了以下幾種基本註解:
它們的執行順序如下:
因此,可以在BMITest.java中,在@Before中創建被測對象,在@After中銷燬被測對象,減少冗餘:
@Before
public void setUp() throws Exception {
testObj = new BMI();
System.out.println("Run @Before method");
}
@After
public void tearDown() throws Exception {
testObj = null;
System.out.println("Run @After method");
}
在BMI.java中添加無參的構造方法:
修改測試方法寫法:
@Test
public void getBMIType1() {
testObj.setParams(45.0, 1.6);
// 調用測試方法
String actual = testObj.getBMIType();
// 校驗測試結果
String except = "偏瘦";
assertTrue(actual==except);
}
修改後的完整 BMITest.java:
package sample.ut;
// 使用junit4的測試
import org.junit.*;
import static org.junit.Assert.*;
public class BMITest {
BMI testObj;
@Before
public void setUp() throws Exception {
testObj = new BMI();
System.out.println("Run @Before method");
}
@After
public void tearDown() throws Exception {
testObj = null;
System.out.println("Run @After method");
}
@BeforeClass
public static void prepareEnvironment(){
System.out.println("Run @BeforeClass method");
}
@AfterClass
public static void RestoreEnvironment(){
System.out.println("Run @AfterClass method");
}
@Test
public void getBMIType1() {
System.out.println("Run getBMIType1 method");
testObj.setParams(45.0, 1.6);
// 調用測試方法
String actual = testObj.getBMIType();
// 校驗測試結果
String except = "偏瘦";
assertTrue(actual==except);
}
@Test
public void getBMIType2() {
System.out.println("Run getBMIType2 method");
testObj.setParams(55.0, 1.6);
// 調用測試方法
String actual = testObj.getBMIType();
// 校驗測試結果
String except = "正常";
assertTrue(actual==except);
}
}
執行結果:
可以清楚的明白註解的執行順序。
測試參數化
爲了使運行多個測試用例的代碼簡潔,可以使用參數化運行器來進行測試。
org.junit.runners.Parameterized
測試步驟:
- 指定參數化運行器 @RunWith(Parameterized.class)
- 準備測試數據(構造注入or屬性注入)
- 添加Test方法,執行測試
構造注入
創建新的測試類BMITestParam.java,創建方法同BMITest.java。
用帶參數的構造函數獲取數據集,分爲以下幾個步驟:
1. 定義參數:定義私有變量,用以保存輸入和與預期輸出。
private double weight; // 體重
private double height; // 身高
private String expected; // 預期分類
2. 引入參數:定義帶參數的構造方法。
public BMITestParam(double w, double h, String exp){
this.weight = w;
this.height = h;
this.expected = exp;
}
3. 準備測試數據:定義一個特殊方法。
@Parameterized.Parameters
public static Collection testDataset(){
return Arrays.asList(
new Object[][]{
{45.0, 1.6, "偏瘦"},
{55.0, 1.6, "正常"},
{68.0, 1.6, "偏胖"},
{80.0, 1.6, "肥胖"}
}
);
}
爲了使測試結果有更好的可讀性,可對Patameters添加內部屬性:
在該例中,可改爲:
@Parameterized.Parameters(name="{index}:getBMIType[{0},{1}]=[{2}]")
完整的測試代碼:
package sample.ut;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import java.util.Arrays;
import java.util.Collection;
import static org.junit.Assert.*;
// 指定參數化運行器
@RunWith(Parameterized.class)
public class BMITestParam {
BMI testObj; // 定義被測類對象
// 1. 定義參數
private double weight; // 體重
private double height; // 身高
private String expected; // 預期分類
// 2. 引入參數(定義構造方法)
public BMITestParam(double w, double h, String exp){
this.weight = w;
this.height = h;
this.expected = exp;
}
// 3. 準備測試數據
@Parameterized.Parameters(name="{index}:getBMIType[{0},{1}]=[{2}]")
public static Collection testDataset(){
return Arrays.asList(
new Object[][]{
{45.0, 1.6, "偏瘦"},
{55.0, 1.6, "正常"},
{68.0, 1.6, "偏胖"},
{80.0, 1.6, "肥胖"}
}
);
}
@Before
public void setUp() throws Exception {
testObj = new BMI(weight, height);
}
@After
public void tearDown() throws Exception {
testObj = null;
}
@Test
public void getBMIType() {
assertTrue(testObj.getBMIType()==expected);
}
}
運行結果:
屬性注入
創建新的測試類BMITestParam2.java,創建方法同BMITest.java。
用屬性指定獲取數據集,分爲以下幾個步驟:
1. 定義參數:定義共有變量,用以保存輸入和預期輸出,並指定每個屬性爲參數:
@Parameterized.Parameter(0)
public double weight; // 體重
@Parameterized.Parameter(1)
public double height; // 身高
@Parameterized.Parameter(2)
public String expected; // 預期分類
2. 準備測試數據:定義一個特殊方法(同構造注入)。
完整測試代碼:
package sample.ut;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import java.util.Arrays;
import java.util.Collection;
import static org.junit.Assert.*;
// 指定參數化運行器
@RunWith(Parameterized.class)
public class BMITestParam2 {
BMI testObj; // 定義被測類對象
// 1. 定義參數
@Parameterized.Parameter(0)
public double weight; // 體重
@Parameterized.Parameter(1)
public double height; // 身高
@Parameterized.Parameter(2)
public String expected; // 預期分類
// 2. 準備測試數據
@Parameterized.Parameters(name="{index}:getBMIType[{0},{1}]=[{2}]")
public static Collection testDataset(){
return Arrays.asList(
new Object[][]{
{45.0, 1.6, "偏瘦"},
{55.0, 1.6, "正常"},
{68.0, 1.6, "偏胖"},
{80.0, 1.6, "肥胖"}
}
);
}
@Before
public void setUp() throws Exception {
testObj = new BMI(weight, height);
}
@After
public void tearDown() throws Exception {
testObj = null;
}
@Test
public void getBMIType() {
assertTrue(testObj.getBMIType()==expected);
}
}
運行結果: