文章目錄
IDEA中使用JUnit4進行高效單元測試
現實需求
傳統測試方法是在main函數裏寫測試代碼,測試效率比較低。原因一是多個測試不能一起運行,二是需要人爲觀察輸出是否正確。
下面以《劍指Offer(第二版)》面試題4爲例,進行說明。
面試題4:二維數組中的查找
題目:在一個二維數組中,每一行都按照從左到右遞增的順序排序,每一列都按照從上到下遞增的順序排序。請完成一個函數,輸入這樣一個二維數組和一個整數,判斷數組中是否含有該整數。
- Java實現
public class FindInMatrix {
/**
* 二維數組中的查找
* @param matrix
* @param rows
* @param columns
* @param num
* @return
*/
public static boolean isFound(int[][] matrix, int rows, int columns, int num){
if(matrix!=null && rows>0 && columns>0){
int row = 0;
int column = columns - 1;
while(row<rows && column>=0){
if(matrix[row][column] == num)
return true;
else if(matrix[row][column] > num)
column--;
else // matrix[row][column] < num
row++;
} // end while
} // end if
return false;
} // end isFound()
} // end class
- 傳統方式測試
public class FindInMatrixApp {
public static void main(String[] args) {
// 一 輸入 & 測試用例
// 1 矩陣是空指針
int[][] matrix01 = null; // output:查找失敗
// 2 矩陣非空
int[][] matrix02 = {
{1,2,8,9},
{2,4,9,12},
{4,7,10,13},
{6,8,11,15}
};
int num01 = 15; // 2.1 整數是最大值 output: 二維數組中存在 15
int num02 = 1; // 2.2 整數是最小值 output: 二維數組中存在 1
int num03 = 9; // 2.3 整數是中間值 output: 二維數組中存在 9
int num04 = 18; // 2.4 整數大於最大值 output: 查找失敗
int num05 = 0; // 2.5 整數小於最小值 output: 查找失敗
int num06 = 5; // 2.6 整數是中間值但不存在 output: 查找失敗
int num = num06;
// 二 執行
// boolean found = FindInMatrix.isFound(matrix01, 4,4,num);
boolean found = FindInMatrix.isFound(matrix02,4,4,num);
// 三 輸出
if(found)
System.out.println("二維數組中存在 " + num);
else
System.out.println("查找失敗");
} // end main()
} // end class
總結:
- 從傳統方式測試代碼中可以看到,有7個測試用例,需要修改和運行“執行部分的代碼”7次,並且每次都需要人爲觀察輸出,判斷是否正確。整個測試過程比較繁瑣。
- 下文將介紹Junit4單元測試工具,並用Junit4測試面試題4,在對比中感受Junit4在測試代碼過程中效率的提升。本文只介紹Junit4的一些基本測試功能,幫助讀者快速上手使用。
IDEA搭建JUnit測試環境
筆者的開發環境:
- jdk-1.7
- Intellij IDEA 2019.3
- apache-maven-3.6.3
安裝JUnit插件
File——>Setting——>Plugins——>搜索JUnit——>下載勾選JUnitGenerator V2.0插件——>勾選IDEA自帶JUnit插件——>Aplply——>OK
配置JUnit插件
File——>Setting——>Other Setting——>JUnit Generator——>Properties——>修改測試用例輸出路徑${SOURCEPATH}/../../test/java/${PACKAGE}/${FILENAME}
——>選擇JUnit4版本——>對默認測試用例模板進行一些修改
修改後的測試用例模板
#macro (cap $strIn)$strIn.valueOf($strIn.charAt(0)).toUpperCase()$strIn.substring(1)#end
## Iterate through the list and generate testcase for every entry.
#foreach ($entry in $entryList)
#set( $testClass="${entry.className}Test")
##
package $entry.packageName;
import org.junit.*;
import static org.junit.Assert.*;
import static org.hamcrest.Matchers.*;
/**
* ${entry.className} Tester.
*
* @author cty
* @date: $today
* @version 1.0
*/
public class $testClass {
@Before
public void before() throws Exception {
} // end before()
@After
public void after() throws Exception {
} // end after()
#foreach($method in $entry.methodList)
/**
* Method: $method.signature
*/
@Test
public void test#cap(${method.name})() throws Exception {
//TODO: Test goes here...
} // end test#cap(${method.name})()
#end
#foreach($method in $entry.privateMethodList)
/**
* Method: $method.signature
*/
@Test
public void test#cap(${method.name})() throws Exception {
//TODO: Test goes here...
#foreach($string in $method.reflectionCode)
$string
#end
} // end test#cap(${method.name})()
#end
} // end $testClass{}
#end
maevn創建jar類型項目
File——>New——>Project——>Maven——>勾選Create feom archetype——>選擇maven-archetype-quickstart——>Next——>修改項目路徑和項目名——>修改組名——>Next——>選擇maven版本——>選擇maven配置文件——>Finish
maven的jar類型項目標準路徑結構
在pom.xml中添加依賴的jar包(以下爲筆者pom.xml文件中的內容)
<?xml version="1.0" encoding="UTF-8"?>
<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.cty</groupId>
<artifactId>find</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
</properties>
<dependencies>
<!-- JUnit4依賴jar包 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<!-- hamcrest斷言依賴jar包 -->
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-library</artifactId>
<version>1.3</version>
</dependency>
</dependencies>
</project>
hamcrest斷言介紹
舊的斷言方法是assert,hamcrest斷言的方法是assertThat,使用起來更加自然。以下是hamcrest斷言的使用示例。
@Test
public void Test(){
int n = 5;
String str = "cty";
double d = 3.0d;
assertThat( n, allOf( greaterThan(1), lessThan(15) ) );
assertThat( n, anyOf( greaterThan(16), lessThan(8) ) );
assertThat( n, anything() );
assertThat( str, is( "cty" ) );
assertThat( str, not( "cty" ) );
assertThat( str, containsString( "cty" ) );
assertThat( str, endsWith("cty" ) );
assertThat( str, startsWith( "cty" ) );
assertThat( n, equalTo(5) );
assertThat( str, equalToIgnoringCase( "cty" ) );
assertThat( str, equalToIgnoringWhiteSpace( "cty" ) );
assertThat( d, closeTo( 3.0, 0.3 ) );
assertThat( d, greaterThan(3.0) );
assertThat( d, lessThan (10.0) );
assertThat( d, greaterThanOrEqualTo (5.0) );
assertThat( d, lessThanOrEqualTo (16.0) );
// assertThat( map, hasEntry( "cty", "cty" ) );
// assertThat( iterable, hasItem ( "cty" ) );
// assertThat( map, hasKey ( "cty" ) );
// assertThat( map, hasValue ( "cty" ) );
}
JUnit4測試面試題4
算法的Java實現
main.java.com.cty.FindFromMatrix 是面試題4的Java實現
生成測試類
方法一:(直接使用測試用例模板)
將鼠標光標放在FindFromMatrix中——>右鍵Generate(或使用快捷鍵 alt+insert)——>JUnit Test——>左鍵點擊JUnit4
方法二:(根據需求自定義測試類內容)
將鼠標光標放在FindFromMatrix中——>(右鍵Go To——>Test)(或快捷鍵 Ctrl+Shift+T)——>Create New Test——>選擇JUnit版本和勾選待測試方法——>OK
測試類中編寫測試代碼
筆者生成測試類使用的方法一。編寫測試代碼後測試類內容如下。
package com.cty.A_Base.program04;
import org.junit.*;
import static org.junit.Assert.*;
import static org.hamcrest.Matchers.*;
/**
* FindInMatrix Tester.
*
* @author cty
* @date: 06/27/2020
* @version 1.0
*/
public class FindFromMatrixTest {
@Before
public void before() throws Exception {
} // end before()
@After
public void after() throws Exception {
} // end after()
/**
* Method: isFound(int[][] matrix, int rows, int columns, int num)
*/
@Test
public void testIsFound() throws Exception {
//TODO: Test goes here...
// 1 矩陣是空指針
int[][] matrix01 = null;
assertThat(FindFromMatrix.isFound(matrix01, 4,4,6), equalTo(false));
// 2 矩陣非空
int[][] matrix02 = {
{1,2,8,9},
{2,4,9,12},
{4,7,10,13},
{6,8,11,15}
};
int num01 = 15; // 2.1 整數是最大值
assertThat(FindFromMatrix.isFound(matrix02, 4,4,num01), equalTo(true));
int num02 = 1; // 2.2 整數是最小值
assertThat(FindFromMatrix.isFound(matrix02, 4,4,num02), equalTo(true));
int num03 = 9; // 2.3 整數是中間值
assertThat(FindFromMatrix.isFound(matrix02, 4,4,num03), equalTo(true));
int num04 = 18; // 2.4 整數大於最大值
assertThat(FindFromMatrix.isFound(matrix02, 4,4,num04), equalTo(false));
int num05 = 0; // 2.5 整數小於最小值
assertThat(FindFromMatrix.isFound(matrix02, 4,4,num05), equalTo(false));
int num06 = 5; // 2.6 整數是中間值但不存在
assertThat(FindFromMatrix.isFound(matrix02, 4,4,num06), equalTo(false));
} // end testIsFound()
} // end FindInMatrixTest{}
一方面,一鍵運行即可測試所有的7種測試用例。
另一方面,測試無誤運行框會閃過綠條,而不需要人爲觀察輸出判斷結果是否正確。這正是JUnit單元測試工具的使用邏輯——Keep the bar green to make code clean!
上述兩方面剛好解決傳統測試方法的缺陷。
故意將“2.1 整數是最大值”的情況改爲錯誤的結果“false”,即:
int num01 = 15; // 2.1 整數是最大值
assertThat(FindFromMatrix.isFound(matrix02, 4,4,num01), equalTo(false));
再次運行,會發現測試出錯的地方會被定位,出錯的原因也會被詳細說,非常方便。
附錄
文章中的測試代碼:Find
說明:將源碼Fork到自己的gitee中,使用Web IDE查看會極度舒適!
參考
[1] 《劍指Offer(第二版)》
[2] idea安裝junit插件進行junit測試