單元測試之junit篇

簡介

關(guān)于單元測試的工具調(diào)研可以參考:https://km.sankuai.com/page/365031302

在構(gòu)建本地單元測試的時(shí)候,JUnit4測試框架是java標(biāo)準(zhǔn)測試庫,junit測試框架可以讓你在編寫測試代碼的中進(jìn)行setup, 卸載, 和斷言等操作。構(gòu)建本地單元測試框架運(yùn)行不需要依賴于真實(shí)設(shè)備或者模擬設(shè)備,可以通過Robolectric庫來實(shí)現(xiàn)對(duì)Android系統(tǒng)框架的依賴,Robolectric庫是可以兼容junit庫的。

通過junt4進(jìn)行本地單元測試,不要依賴于android運(yùn)行環(huán)境,因此運(yùn)行速度更快,可以配合Truth庫快速測試某個(gè)方法是否符合預(yù)期的程序設(shè)計(jì)。在編寫測試代碼的時(shí)候,可以按照業(yè)務(wù)實(shí)現(xiàn)類來新建測試類,每個(gè)Junit4測試類對(duì)應(yīng)一個(gè)需要測試的業(yè)務(wù)代碼,每個(gè)被@Test注解的測試方法是需要被測試的public方法用于驗(yàn)證業(yè)務(wù)功能等。

測試環(huán)境搭建

在程序中引入junit庫,在moudule的build.gradle中配置,其中truth庫是為了斷言使用。

testImplementation 'junit:junit:4.12'
//斷言庫,替換junit的api
testImplementation "com.google.truth:truth:1.0.1"

在 Android Studio 項(xiàng)目中,將本地單元測試的源文件存儲(chǔ)在 module-name/src/test/java/ 目錄下,通常在新建完項(xiàng)目以后,該目錄會(huì)自動(dòng)創(chuàng)建,并且會(huì)存在一個(gè)默認(rèn)的測試用例代碼。

代碼目錄結(jié)構(gòu)如下:

module-name/src

├── androidTestjava (插樁單元測試、Espresso測試)

├── main/java (業(yè)務(wù)代碼)

├── test/java (本地單元測試)

public class ExampleUnitTest {
    @Test
    public void addition_isCorrect() {
        assertEquals(4, 2 + 2);
    }
}

常見API:參閱文檔 JUnit annotations 和 Android annotations.

@Before: 使用這個(gè)注解可以指定一段包含測試設(shè)置操作的代碼。測試類在每個(gè)測試執(zhí)行前調(diào)用這段代碼。你可以定義多個(gè)帶有@Before注解的方法, 但是在測試類中這個(gè)方法執(zhí)行的順序是不明確的。

@After: 這個(gè)注解指定一段代碼包含測試卸載操作。在每個(gè)測試方法執(zhí)行后調(diào)用這段代碼。你可以定義多個(gè)@After操作的代碼。使用這個(gè)注解來釋放內(nèi)存中的資源。

@Test: 使用這個(gè)注解標(biāo)識(shí)一個(gè)測試方法。 一個(gè)單獨(dú)的測試類可以對(duì)應(yīng)多個(gè)測試方法。

@Rule: @Rule通過復(fù)用的方法,可以允許你可以靈活的添加和修改每個(gè)測試方法。 在Android測試中, 此注解需要和Android測試支持庫中提供的測試規(guī)則類配合命用。比如 ActivityTestRule和 ServiceTestRule

@BeforeClass: 使用此注解來指定一個(gè)測試類的靜態(tài)方法只能調(diào)用一次。這種測試步驟對(duì)于耗時(shí)操作非常有用, 例如連接數(shù)據(jù)庫操作。

@AfterClass: 使用這個(gè)注解來指定一個(gè)靜態(tài)方法, 當(dāng)類中所有的測試方法都已經(jīng)運(yùn)行完成的時(shí)候調(diào)用。 這個(gè)步驟對(duì)釋放@BeforeClass塊中占用的資源非常有用。

@Test(timeout=): 一些注解支持在注解中設(shè)置變量值。 例如, 你可以指定一個(gè)測試的超時(shí)時(shí)間,如果一個(gè)測試開始并且沒有在指定的超時(shí)時(shí)間內(nèi)完成, 它自動(dòng)認(rèn)為校驗(yàn)失敗。超時(shí)時(shí)間的單位是毫秒, 如 @Test(timeout=5000)。

@Ignore:讓Junit忽略某些測試方法,可能是由于測試方法沒有完全編寫完成或者太過于耗時(shí)。

@Test(expected = NullPointerException.class):驗(yàn)證測試方法會(huì)拋出某些異常,在Junit測試中通過設(shè)置expected參數(shù)指定異常類型例如NullPointerException空指針異常,如果該測試方法拋出IllegalArgumentException異常則綠色passed,如果沒有拋出的話,則測試紅色failed失敗。

示例代碼:

獲取三個(gè)數(shù)中最大的那個(gè)數(shù):這個(gè)為了說明setup的操作,沒有把max方法寫成static類型。

public class MathUtil {
   public int max(int a, int b, int c){
       if(a > b){
           if(a > c){
               return a;
           }else{
               return c;
           }
        }else{
           if(b > c){
               return b;
           }else{
               return c;
           }
        }
    }
}

測試代碼

測試代碼簡單分析:

@Before 注解的setup方法可以讓測試程序處理一些初始化操作,比如公有的對(duì)象初始化比如下面的代碼創(chuàng)建了mathUtil對(duì)象。,如果這個(gè)對(duì)象不單單是在一個(gè)測試方法用的對(duì)象話,這樣可以避免在每個(gè)測試類中都編寫創(chuàng)建該對(duì)象的邏輯。在運(yùn)行測試代碼的時(shí)候,首先會(huì)執(zhí)行被@Before注解的方法,注意:被@Before注解的方法,不是執(zhí)行一次,而是每個(gè)被@Test注解的方法執(zhí)行之前都是調(diào)用setup方法。

@After注解的方法,主要用于釋放資源,一般很少用到,比如文件關(guān)閉,數(shù)據(jù)庫斷開鏈接之類的。和@Before一樣,每個(gè)測試方法執(zhí)行完以后,也都會(huì)調(diào)用@After方法。

驗(yàn)證單元測試的結(jié)果,junit本身提供了一整套斷言功能,但是目前推薦使用Truth庫,下面用的就是Truth庫中的比較兩個(gè)int是否相等的邏輯。斷言的邏輯比較簡單,更多的API可以參考Truth庫

public class MathUtilTest {
        MathUtil mathUtil;
    @Before 
    public void setup() { 
        mathUtil = new MathUtil();
    }
    @Test
    public void testMax() {
           Truth.assertThat(mathUtil.max(1, 2, 3)).isEqualTo(3);
    }
    @After
    fun releaseResource(){
        
    }
}

測試結(jié)果

參考:https://blog.csdn.net/u011060103/article/details/107297512

總結(jié)

本文主要介紹junit的常見api和Truth斷言庫的簡單使用,整體來看junit是比較簡單的,可以針對(duì)一些public方法方法做單元測試并驗(yàn)證單元測試的結(jié)果是否符合預(yù)期。但是我們?cè)趯?shí)際業(yè)務(wù)開發(fā)的時(shí)候往往沒有這么簡單,主要涉及到以下幾個(gè)問題:

(1)類中存在大量的private方法,在實(shí)際業(yè)務(wù)開發(fā)中,public方法往往只是對(duì)外暴露沒有實(shí)際邏輯,實(shí)際邏輯都寫在private中,而junit不能直接測試private方法。

(2)對(duì)于沒有返回值的方法,junit無法斷言,這個(gè)時(shí)候我們有需要測試該void方法是否得到執(zhí)行。

(3)如果有的方法依賴于Android環(huán)境,比如content等。

解決以上的問題,需要借助于Robolectric 或模擬框架(如Mockito庫)來實(shí)現(xiàn)上述問題。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 單元測試是編寫測試代碼,應(yīng)該準(zhǔn)確、快速地保證程序基本模塊的正確性。 好的單元測試的標(biāo)準(zhǔn) w3cschool h...
    音樂與咖啡Bean閱讀 130評(píng)論 0 0
  • 前言 單元測試是軟件開發(fā)中必不可少的一環(huán),但是在平常開發(fā)中往往因?yàn)轫?xiàng)目周期緊,工作量大而被選擇忽略,這樣往往導(dǎo)致軟...
    聞人的技術(shù)博客閱讀 1,636評(píng)論 0 9
  • 單元測試是什么 首先我們來介紹一下什么是單元測試?可能有很多人經(jīng)常會(huì)聽到這個(gè)詞并不感到陌生,那什么是單元測試呢,在...
    水木飛雪閱讀 16,933評(píng)論 0 29
  • 原文:http://www.itdecent.cn/p/a2aaa020cb03 前言 單元測試是軟件開發(fā)中必不...
    xiaotian是個(gè)混子閱讀 677評(píng)論 0 6
  • JUnit4 JUnit是一個(gè)幫助編寫和執(zhí)行單元測試的框架??赡芎芏嗳硕冀佑|過單元測試,但是只是停留在copy別人...
    申國駿閱讀 1,971評(píng)論 0 1

友情鏈接更多精彩內(nèi)容