單元測試——IDEA中使用JUnit4進行高效單元測試

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測試環境

筆者的開發環境:

  1. jdk-1.7
  2. Intellij IDEA 2019.3
  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測試

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章