1. 程式人生 > 實用技巧 >【JUnit測試】總結

【JUnit測試】總結

什麼是Junit?

Junit是xUnit的一個子集,在c++,paython,java語言中測試框架的名字都不相同
xUnit是一套基於測試驅動開發的測試框架
其中的斷言機制:將程式預期的結果與程式執行的最終結果進行比對,確保對結果的可預知性
java所用的測試工具是Junit

使用 JUnit 需要匯入 JUnit 包。官方網站:https://junit.org/junit5/
在不同編譯器下的導包過程不一樣,這裡以 Maven 為例

<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>

測試流程

建立測試檔案

  1. 新建一個原始碼目錄來存放我們的測試程式碼
  2. 測試類的包應該和被測試類保持一致
  3. 測試方法上必須使用 @Test 進行修飾
  4. 測試方法必須使用 public void 進行修飾,不能帶任何的引數
  5. 測試單元中的每個方法必須可以獨立測試,測試方法間不能有任何的依賴
  6. 測試類使用 Test 作為類名的字尾(不是必須)
  7. 測試方法使用 test 作為方法名的字首(不是必須)

目的碼:

package com.imooc.util;

public class Calculate {
public int add(int a,int b) {
return a + b;
} public int subtract(int a, int b) {
return a - b;
} public int multiply(int a,int b) {
return a * b;
} public int divide(int a ,int b) {
return a / b;
}
}

建立測試程式碼

右鍵選中需要測試的目的碼,建立 JUnit Test Case 測試用例。




測試程式碼:

package com.imooc.util;

import static org.junit.Assert.*;

import org.junit.Test;

public class CalculateTest {

    /*
* 1.測試方法上必須使用@Test進行修飾
* 2.測試方法必須使用public void 進行修飾,不能帶任何的引數
* 3.新建一個原始碼目錄來存放我們的測試程式碼
* 4.測試類的包應該和被測試類保持一致
* 5.測試單元中的每個方法必須可以獨立測試,測試方法間不能有任何的依賴
* 6.測試類使用Test作為類名的字尾(不是必須)
* 7.測試方法使用test作為方法名的字首(不是必須)
*/
@Test
public void testAdd() {
assertEquals(6, new Calculate().add(3,3));
} @Test
public void testSubtract() {
assertEquals(3, new Calculate().subtract(5,2));
} @Test
public void testMultiply() {
assertEquals(4, new Calculate().multiply(2, 2));
} @Test
public void testDivide() {
assertEquals(3, new Calculate().divide(6, 2));
}
}


注意:

  1. Failure 一般由單元測試使用的斷言方法判斷失敗所引起的,這表示在測試點發現了問題,即 程式輸出的結果和我們預期的不一樣。
  2. error 是由程式碼異常引起的,它可以產生於測試程式碼本身的錯誤,也可以是被測試程式碼中的一個隱藏 bug。
  3. 測試用例不說用來證明你是對的,而是用來證明你沒有錯

註釋

演示程式碼:

package com.imooc.util;

import static org.junit.Assert.*;

import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test; public class JunitFlowTest { /*
* [email protected]修飾的方法會在所有方法被呼叫前被執行,
* 而且該方法是靜態的,所以當測試類被載入後接著就會執行它,
* 而且在記憶體中它只會存在一份例項,它比較適合載入配置檔案。
* [email protected]所修飾的方法通常用來對資源的清理,如關閉資料庫的連線
* [email protected]和@After會在每個測試方法的前後各執行一次。
*
*/
@BeforeClass
public static void setUpBeforeClass() throws Exception {
System.out.println("this is beforeClass...");
} @AfterClass
public static void tearDownAfterClass() throws Exception {
System.out.println("this is afterClass...");
} @Before
public void setUp() throws Exception {
System.out.println("this is before...");
} @After
public void tearDown() throws Exception {
System.out.println("this is after");
} @Test
public void test1() {
System.out.println("this is test1...");
} @Test
public void test2(){
System.out.println("this is test2...");
} }

執行結果:

隱藏的固定程式碼:

  1. @BeforeClass 修飾的方法會在所有方法被呼叫前被執行,而且該方法是靜態的,所以當測試類被載入後接著就會執行它,而且在記憶體中它只會存在一份例項,它比較適合載入配置檔案以及一些只用載入一次的東西。
  2. @AfterClass 所修飾的方法通常用來堆資源的清理,如關閉資料庫的連線
  3. @Before@After 會在每個測試方法的前後各執行一次。

    這些都是固定程式碼,執行時一定會被執行


常用註釋:

  • @Test:將一個普通的方法修飾成為一個測試方法

    • @Test(expected=XX.class)
    • @Test(timeout=毫秒)

-@BeforeClass:它會在所有的方法執行前被執行,static 修飾
-@AfterClass:它會在所有的方法執行結束後被執行,static 修飾

  • @Before:會在每一個測試方法被執行前執行一次
  • @After:會在每一個測試方法執行後被執行一次
  • @Ignore:所修飾的測試方法會被測試執行器忽略
  • @RunWith:可以更改測試執行器(如想自定義測試執行器可繼承 org.junit.runner.Runner)
    可以配合測試套件使用。

測試套件

測試套件:可以組織測試類一起執行。

  1. 寫一個作為測試套件的入口類,這個類裡不包含其他的方法
  2. 更改測試執行器為 @RunWith(Suite.class)
  3. 將要測試的類作為陣列傳入到 @Suite.SuiteClasses({A,B,...})

演示程式碼:

package com.imooc.util;

import static org.junit.Assert.*;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Suite; @RunWith(Suite.class)
@Suite.SuiteClasses({TaskTest1.class,TaskTest2.class,TaskTest3.class})
public class SuiteTest {
/*
* 1.測試套件就是組織測試類一起執行的
*
* 寫一個作為測試套件的入口類,這個類裡不包含其他的方法
* 更改測試執行器Suite.class
* 將要測試的類作為陣列傳入到Suite.SuiteClasses({})
*/
}

這段程式碼可以將 TaskTest1、2、3 同時執行測試。從而達到測試套件的效果。

引數化設定

  1. 更改預設的測試執行器為 @RunWith(Parameterized.class)
  2. 宣告變數來存放預期值和結果值
  3. 宣告一個返回值為 Collection<> 的公共靜態方法,並使用 @Parameters 進行修飾
  4. 為測試類宣告一個帶有引數的公共建構函式,並在其中為之宣告變數賦值
  5. 編寫測試方法,使用變數

演示程式碼:

package com.imooc.util;

import static org.junit.Assert.*;

import java.util.Arrays;
import java.util.Collection; import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters; @RunWith(Parameterized.class)
public class ParameterTest {
/*
* 1.更改預設的測試執行器為RunWith(Parameterized.class)
* 2.宣告變數來存放預期值 和結果值
* 3.宣告一個返回值 為Collection的公共靜態方法,並使用@Parameters進行修飾
* 4.為測試類宣告一個帶有引數的公共建構函式,並在其中為之宣告變數賦值
*/
int expected = 0;//預期值
int input1 = 0;//輸入值1
int input2 = 0;//輸入值2 @Parameters //可以將返回的引數依次放入構造方法中進行測試
public static Collection<Object[]> t() {
return Arrays.asList(new Object[][]{
{3,1,2},//預期值,輸入值1,輸入值2
{4,2,2}
}) ;
} public ParameterTest(int expected,int input1,int input2) {
this.expected = expected;
this.input1 = input1;
this.input2 = input2;
} @Test
public void testAdd() {
assertEquals(expected, new Calculate().add(input1, input2));
} }

在 Spring 中進行測試

Spring 配置檔案

<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="configLocation" value="classpath:hibernate.cfg.xml"/>
</bean>
<bean id="date" class="java.util.Date"/>
</beans>

Spring 測試程式碼

package com.imooc.conform;

import java.util.Date;

import org.junit.BeforeClass;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; public class SpringTest { private static ApplicationContext context = null;
@BeforeClass
public static void setUpBeforeClass() throws Exception {
context = new ClassPathXmlApplicationContext("applicationContext.xml");
} @Test
public void test() {
Date date = (Date) context.getBean("date");
System.out.println(date);
}
}