一、單元測試的目的?
單元測試是編寫測試代碼,用以檢測特定的、明確的、細顆粒的功能! 嚴格來說,單元測試只針對功能點進行測試,不包括對業務流程正確性的測試。現在一般公司都會進行業務流程的測試,這也要求測試人員需要了解需求! 測試人員也不好過啊~~
目前開發所用的單元是Junit框架,在大多數java的開發環境中已經集成,可以方便開發自己調用!
注意:單元測試不僅僅是要保證代碼的正確性,一份好的單元測試報告,還要完整地記錄問題的所在和缺陷以及正確的狀態,方便后面代碼的修復,重構和改進!
二、單元測試做什么?
一般來說,一份單元測試主要包括以下幾個方面:
==============================================================================================
1.接口功能性測試: 接口功能的正確性,即保證接口能夠被正常調用,並輸出有效數據!
------------------> 是否被順利調用
------------------> 參數是否符合預期
==============================================================================================
2.局部數據結構測試:保證數據結構的正確性
------------------> 變量是否有初始值或在某場景下是否有默認值
------------------> 變量是否溢出
==============================================================================================
3.邊界條件測試:測試
------------------> 變量無賦值(null)
------------------> 變量是數值或字符
------------------> 主要邊界:最大值,最小值,無窮大
------------------> 溢出邊界:在邊界外面取值+/-1
------------------> 臨近邊界:在邊界值之內取值+/-1
------------------> 字符串的邊界,引用 "變量字符"的邊界
------------------> 字符串的設置,空字符串
------------------> 字符串的應用長度測試
------------------> 空白集合
------------------> 目標集合的類型和應用邊界
------------------> 集合的次序
------------------> 變量是規律的,測試無窮大的極限,無窮小的極限
==============================================================================================
4.所有獨立代碼測試:保證每一句代碼,所有分支都測試完成,主要包括代碼覆蓋率,異常處理通路測試
------------------> 語句覆蓋率:每個語句都執行到了
------------------> 判定覆蓋率:每個分支都執行到了
------------------> 條件覆蓋率:每個條件都返回布爾
------------------> 路徑覆蓋率:每個路徑都覆蓋到了
==============================================================================================
5.異常模塊測試,后續處理模塊測試:是否包閉當前異常或者對異常形成消化,是否影響結果!
三、JAVA的單元測試JUNIT4
(1):業務流程的一般是按照需求的預期效果,跑完整個業務流程,包括以前開發的流程
-----------------> 是否實現了預期
-----------------> 是否影響到了以前的流程
-----------------> 全流程是否順利
-----------------> 數據是否符合預期
==============================================================================================
(2):代碼測試:
-
@BeforeClass 全局只會執行一次,而且是第一個運行
-
@Before 在測試方法運行之前運行
-
@Test 測試方法
-
@After 在測試方法運行之后允許
-
@AfterClass 全局只會執行一次,而且是最后一個運行
-
@Ignore 忽略此方法
JUNIT4是以org.junit為框架進行的測試,以注解的形式來識別代碼中需要測試的方法!
注意:
對於每一個測試,我們都應該保持獨立測試,以確保測試結果是有意義的。在程序中,經常會出現,當測試完一個方法后,其參數已經被系統保持或持久化下來。無疑會造成下一次的測試測試數據或者狀態的不合理性!為了解決問題,對於此類場景,我們的測試代碼必須具備初始化和收尾的能力。也即是@Before和@After的意義所在!
同理@AfterClass和BeforeClass即是為了滿足測試中,那些體積非常大,但只要一次初始化的代碼塊!
(3):斷言測試與及常用斷言:
---------->assertEquals:
-
Assert.assertEquals(
"此處輸出提示語",
5, result);
-
-
===================================================================================================================
-
解析:
"此處輸出提示語" 為錯誤時你個人想要輸出的錯誤信息;
5 是指你期望的值;result 是指你調用程序后程序輸出給你的結果
-
-
@Test(expected = NullPointerException.class)
-
解析:在注解的時候添加expected 為忽略此異常
-
@Test(timeout = 5000 ):超時設置
-
@Test(expected = XXXXException. class):期望出現異常,如果出現該異常則成功,否則測試失敗
-
@Ignore() :用戶方法之上,被注解的方法會被成功需忽略
-
===================================================================================================================
-
-
fail(
"Not yet implemented")
-
解析:放在方法中,如果我順利地執行,我就報失敗出來。就是說按道理不應該執行到這里的,但是偏偏執行了,說明程序有問題
-
===================================================================================================================
-
Assert.assertTrue(
"msg",boolean)與Assert.assertFalse(
"msg",boolean)
-
解析:如果和預期一樣為
true則成功,否則失敗輸出msg;如果和預期一樣為
false則成功,否則失敗並輸出
----------> assertNull("msg",boolean)與assertNotNull("msg",boolean)
解析:assertNull與assertNotNull可以驗證所測試的對象是否為空或不為空,如果和預期的相同則測試成功,否則測試失敗!
========================================主要常用方法============================================
斷言列表:
-------------->assertTrue(String message, boolean condition) 要求condition == true
-------------->assertFalse(String message, boolean condition) 要求condition == false
-------------->assertEquals(String message, XXX expected,XXX actual) 要求expected期望的值能夠等於actual
-------------->assertArrayEquals(String message, XXX[] expecteds,XXX [] actuals) 要求expected.equalsArray(actual)
-------------->assertNotNull(String message, Object object) 要求object!=null
-------------->assertNull(String message, Object object) 要求object==null
-------------->assertSame(String message, Object expected, Object actual) 要求expected == actual
-------------->assertNotSame(String message, Object unexpected,Object actual) 要求expected != actual
-------------->assertThat(String reason, T actual, Matcher matcher) 要求matcher.matches(actual) == true
-------------->fail(String message) 要求執行的目標結構必然失敗,同樣要求代碼不可達,即是這個方法在程序運行后不會成功返回,如果成功返回了則報錯
(4):運行器指定?
單元測試中,每個類都是由於JUNIT4框架中的Runner運行器來執行的。一般情況下,在沒有指定運行器的時候,是由系統默認選擇(TestClassRunner)的運行器執行。包括類中的所有方法都是由該運行器負責調用和執行。當我們需要指定的時候,則通過類級別注解 @Run Wirth(xxxxxx)進行選擇,一般是根據不同類型選擇不同執行器,可以提高效率也可以應用於某種特殊場景!
(5):參數化測試?
-
@RunWith(Parameterized.
class )
-
public
class
TestParam {
-
-
private
static Calculator calculator =
new Calculator();
//需要測試的類
-
private
int param;
-
private
int result;
-
-
@Parameters
-
public static Collection data(){
-
-
return Arrays.asList(
new Object[][] {{
11 ,
17 } , { xx1 , xx} } );
-
-
}
-
-
//有參構造,在實例的時候實現參數初始化
-
public TestParam( int param, int result){
-
this .param = param;
-
this .result = result;
-
}
-
-
@Test
-
public void TestResult(){
-
calculator.square(param);
-
assertEquals(result, calculator.getResult());
-
}
-
-
}
解說:參數化測試的目標是為了一次性完成同類型測試,將相同類型的數據按照一定的順序批量地傳入測試方法,並得出結論!其本質是一個批量的化的操作,只是為了方便我們測試而進行了封裝。我們只有提供測試的方法以及按照一定的順序進行設置則可以。
--------->進行類注解:@RunWith(Parameterized.class),為了測試類指定一個ParameterizedRunner運行器
--------->進行參數設置:將測試結果和期望結果,以每一組都是一個數組的形式存放以形成二維數組,轉化為list返回並注解。
--------->參數初始化:設置測試方法要入參的參數,並按照"參數設置"的順序利用構造方法進行初始化的賦值!
--------->測試調用:寫一個測試方法進行調用,將參數傳遞到要測試的類的方法中並返回數據
注意:參數化測試需要創建一單獨用於測試的測試類。並定義兩個變量用於接受測試結果和預期目標。數據存放以二維數組的方式,兩個為一組。接着便是通過構造方法進行數據初始化。 構造方法入參的順序要和二維數組中國每一組存放的數據順序保持一致。
(6):打包測試?
-
@RunWith(Suite. class )
-
@Suite.SuiteClasses( {CalculatorTest.
class ,SquareTest. class } )
-
public
class AllCalculatorTests {
-
//to do something;
-
}
-
==========================================================================================================================
-
解析:將有需要的一起執行程序一起打包,然后執行
-
運行器:Suite.
class
解析:我們把需要打包一起測試的測試類作為參數傳遞給該注解。然后直接運行代碼,此處的測試類可以直接設置為空,只需要添加注解便OK;