成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

Android 單元測(cè)試: 首先,從是什么開始

DevTTL / 2488人閱讀

摘要:所以,寫單元測(cè)試,就是給你的每個(gè)類的每個(gè)方法寫對(duì)于的測(cè)試方法。常見的單元測(cè)試框架有等等。那么我們給這個(gè)東西做單元測(cè)試的時(shí)候,不是測(cè)這一整個(gè)流程。叫做集成測(cè)試,而不是單元測(cè)試。那對(duì)于這個(gè)例子,單元測(cè)試是怎么樣的呢這個(gè)請(qǐng)看下一小節(jié)。

這是一系列安卓單元測(cè)試的文章,目測(cè)主要會(huì)cover以下的主題:

什么是單元測(cè)試

為什么要做單元測(cè)試

JUnit

Mockito

Robolectric

Dagger2

一個(gè)具體的app例子實(shí)踐

神秘的bonus

什么是單元測(cè)試

首先需要介紹一下什么是單元測(cè)試。很多人像我一樣,本科并不是計(jì)算機(jī)專業(yè)出身的,如果在職的公司不要求做單元測(cè)試的話,可能對(duì)這個(gè)詞并沒有一個(gè)確切的概念。而即使是計(jì)算機(jī)專業(yè)出身,如果畢業(yè)以后寫的不多的話,可能對(duì)這個(gè)詞的含義也不是很清楚。從名字上看,單元測(cè)試是為了測(cè)試某一個(gè)代碼單元而寫的測(cè)試代碼。但是什么叫“一個(gè)代碼單元”呢?是一個(gè)模塊、還是一個(gè)類、還是一個(gè)方法(函數(shù))呢?不同的人、不同的語言,都有不同的理解。一般的定義,尤其是是在OOP領(lǐng)域,是一個(gè)類的一個(gè)方法。在此,我們也這樣理解:?jiǎn)卧獪y(cè)試,是為了測(cè)試某一個(gè)類的某一個(gè)方法能否正常工作,而寫的測(cè)試代碼。

我們舉一個(gè)例子說明一下,假如你有一個(gè)類,定義如下:

public class Calculator {
    public int add(int one, int another) {
        //為了簡(jiǎn)單起見,暫不考慮溢出等情況。
        return one + another;
    }
}

那么為了測(cè)試這個(gè)Calculator類的add()方法,我們可以寫如下的單元測(cè)試代碼:

public class CalculatorTest {
    public void testAdd() throws Exception {
        Calculator calculator = new Calculator();
        int sum = calculator.add(1, 2);
        Assert.assertEquals(3, sum);
    }
}

這里的CalculatorTestCalculator對(duì)應(yīng)的測(cè)試類。而這里的testAdd()就是add()這個(gè)方法對(duì)應(yīng)的測(cè)試方法。所以,寫單元測(cè)試,就是給你的每個(gè)類的每個(gè)public方法寫對(duì)于的測(cè)試方法。非public方法我們一般是不測(cè)試的,雖然可以通過反射等手段去做,但是一般看來,非public方法是這個(gè)類的實(shí)現(xiàn)細(xì)節(jié),我們并不關(guān)心,我們只關(guān)心某一個(gè)public方法的輸入、輸出。

一般來說,一個(gè)方法對(duì)應(yīng)的測(cè)試方法主要分為3部分,以上面的測(cè)試方法為例:

setup。一般是new出你要測(cè)試的那個(gè)類,以及其他一些前提條件的設(shè)置:Calculator calculator = new Calculator();

執(zhí)行操作。一般是調(diào)用你要測(cè)試的那個(gè)方法,獲得運(yùn)行結(jié)果:int sum = calculator.add(1, 2);

驗(yàn)證結(jié)果。驗(yàn)證得到的結(jié)果跟預(yù)期中是一樣的:Assert.assertEquals(3, sum);

一般來說,我們寫單元測(cè)試,會(huì)用到一些單元測(cè)試框架。常見的Java單元測(cè)試框架有JUnit、TestNG等等。在這個(gè)系列的文章中,我采用JUnit 4,這也是用的最多的一個(gè)測(cè)試框架。上面的第三部,Assert.assertEquals(3, sum); 用的就是JUnit里面的驗(yàn)證結(jié)果的方法,最常見的就是調(diào)用Assert類的一些assert方法。除了上面用到的assertEquals,還有assertTrue, assertNotNull等等。關(guān)于JUnit,我會(huì)在后面的系列文章中專門介紹。

如何在一個(gè)android project里面運(yùn)行單元測(cè)試

我們知道,在一個(gè)android gradle project中,源代碼默認(rèn)是放在src/main/java下面的。而對(duì)應(yīng)的單元測(cè)試代碼則是放在src/test/java下面的,如下圖所示:

其中的package name可以隨意定,很多人喜歡跟src package name保持一致,我個(gè)人習(xí)慣在最后加上.test后綴,因?yàn)锳ndroidStudio太智能了,經(jīng)常我需要重命名單元測(cè)試的package的時(shí)候,AndroidStudio會(huì)把src的package也給重命名了。

打開CalculatorTest,用鼠標(biāo)右鍵點(diǎn)擊testAdd()方法,選擇Run testAdd(), 如下圖所示:

從圖中你可以看出,你可以按快捷鍵Ctrl+Shift+R快速運(yùn)行,當(dāng)然,這要求你的光標(biāo)當(dāng)前焦點(diǎn)是在這個(gè)方法內(nèi)部的。如果你的焦點(diǎn)是在類內(nèi)部,而不在某一個(gè)測(cè)試方法內(nèi)部,那么Ctrl+Shift+R將運(yùn)行這個(gè)測(cè)試類的所有測(cè)試方法。當(dāng)然,你也可以通過右鍵點(diǎn)擊測(cè)試類名來運(yùn)行這個(gè)測(cè)試類里面的所有測(cè)試方法。

運(yùn)行結(jié)束以后,你會(huì)在底部的“Run”這個(gè)tab看到運(yùn)行的結(jié)果,如下圖所示:

除了在AndroidStudio里面運(yùn)行,你還可以在命令行通過gradle testDebugUnitTest,或者是gradle testReleaseUnitTest,分別運(yùn)行debug和release版本的unit testing,這種方式可以一次性運(yùn)行所有測(cè)試類的所有測(cè)試方法。 這種方式的運(yùn)行結(jié)果如下圖所示:

每個(gè)test case的報(bào)告可以在project_root/app/build/reports/tests/debug/index.html 這個(gè)xml里面看到。大致如下圖:

這篇文章的代碼在github上,感興趣的可以clone下來自己試試。

單元測(cè)試不是集成測(cè)試

這里需要強(qiáng)調(diào)一個(gè)觀念,那就是單元測(cè)試只是測(cè)試一個(gè)方法單元,它不是測(cè)試一整個(gè)流程。舉個(gè)例子來說,一個(gè)Login頁面,上面有兩個(gè)輸入框和一個(gè)button。兩個(gè)輸入框分別用于輸入用戶名和密碼。點(diǎn)擊button以后,有一個(gè)UserManager會(huì)去執(zhí)行performlogin操作,然后將結(jié)果返回,更新頁面。

那么我們給這個(gè)東西做單元測(cè)試的時(shí)候,不是測(cè)這一整個(gè)login流程。這種整個(gè)流程的測(cè)試:給兩個(gè)輸入框設(shè)置正確的用戶名和密碼,點(diǎn)擊login button, 最后頁面得到更新。叫做集成測(cè)試,而不是單元測(cè)試。當(dāng)然,集成測(cè)試也是有他的必要性的,然而這不是我們每個(gè)程序員應(yīng)該花多少精力所在的地方。在這方面,有一個(gè)理論叫做Test Pyramid,如下圖所示:

Test Pyramid理論基本大意是,單元測(cè)試是基礎(chǔ),是我們應(yīng)該花絕大多數(shù)時(shí)間去寫的部分,而集成測(cè)試等應(yīng)該是冰山上面能看見的那一小部分。

為什么是這樣呢?因?yàn)榧蓽y(cè)試設(shè)置起來很麻煩,運(yùn)行起來很慢,發(fā)現(xiàn)的bug少,在保證代碼質(zhì)量、改善代碼設(shè)計(jì)方面更起不到任何作用,因此它的重要程度并不是那么高,也無法將它納入我們正常的工作流程中。

而單元測(cè)試則剛好相反,它運(yùn)行速度超快,能發(fā)現(xiàn)的bug更多,在開發(fā)時(shí)能引導(dǎo)更好的代碼設(shè)計(jì),在重構(gòu)時(shí)能保證重構(gòu)的正確性,因此它能保證我們的代碼在一個(gè)比較高的質(zhì)量水平上。同時(shí)因?yàn)檫\(yùn)行速度快,我們很容易把它納入到我們正常的開發(fā)流程中。

至于為什么集成測(cè)試發(fā)現(xiàn)的bug少,而單元測(cè)試發(fā)現(xiàn)的bug多,這里也稍作解釋,因?yàn)榧蓽y(cè)試不能測(cè)試到其中每個(gè)環(huán)節(jié)的每個(gè)方面,某一個(gè)集成測(cè)試運(yùn)行正確了,不代表另一個(gè)集成測(cè)試也能運(yùn)行正確。而單元測(cè)試會(huì)比較完整的測(cè)試每個(gè)單元的各種不同的狀況、臨界條件等等。一般來說,如果每一個(gè)環(huán)節(jié)是對(duì)的,那么在很大的概率上(雖然不是100%),整個(gè)流程就是對(duì)的。所以,集成測(cè)試需要有,但應(yīng)該是少量,單元測(cè)試才是我們應(yīng)該花重點(diǎn)去做的事情。

那對(duì)于這個(gè)例子,單元測(cè)試是怎么樣的呢?這個(gè)請(qǐng)看下一小節(jié)。

兩種函數(shù)(方法),兩種不同的測(cè)試方式

一個(gè)類的方法可以分為兩種,一種是有返回值的,另一種是沒有返回值的。對(duì)于有返回值的方法,我們要測(cè)起來比較容易,就跟上面的Calculator例子那樣,輸入相應(yīng)的參數(shù),得到相應(yīng)的返回值,然后驗(yàn)證得到的返回值跟我們預(yù)期的值一樣,就好了。

但是沒有返回值的方法,要怎么測(cè)試呢?比如說剛剛login的例子,點(diǎn)擊那個(gè)按鈕,會(huì)執(zhí)行Activity的login()方法,它的定義如下:

public void login() {
    String username = ...//get username from username EditText
    String password = ...//get password from password EditText
    //do other operation like validation, etc
    ...
    
    mUserManager.performlogin(username, password);
}

這個(gè)方法是void的,那么怎么驗(yàn)證這個(gè)方法是正確的呢?其實(shí)仔細(xì)想想,這個(gè)方法也是有輸出的,它的輸出就是,調(diào)用了mUserManagerperformLogin方法,同時(shí)傳給他兩個(gè)參數(shù)。所以只要驗(yàn)證mUserManagerperformLogin方法得到了調(diào)用,同時(shí)傳給他的參數(shù)是正確的,就說明這個(gè)方法是能正常工作的。

那怎么樣驗(yàn)證這個(gè)Activity的login()方法,會(huì)調(diào)用mUserManagerperformLogin方法呢?這里涉及到mock的概念,在后面的文章關(guān)于Mockito的使用的時(shí)候,會(huì)介紹到,這里簡(jiǎn)單解釋下,那就是在測(cè)試環(huán)境下,我們會(huì)使用一套mock framework(Mockito),生成一個(gè)mock的UserManager然后賦值給mUserManager,因?yàn)檫@個(gè)mUserManager是通過mock framework生成的,所以這個(gè)mock framework可以驗(yàn)證它的什么方法被調(diào)用了,參數(shù)是什么,等等。

小結(jié)

上面講述了單元測(cè)試的定義,以及與集成測(cè)試的區(qū)別,一般來說,單元測(cè)試不會(huì)接觸到數(shù)據(jù)庫,不會(huì)接觸到網(wǎng)絡(luò),不會(huì)接觸到一些復(fù)雜的外部環(huán)境,如果有的話,那可能是你測(cè)試的方式有誤,測(cè)試的粒度不夠“單元”,希望這篇文章能將這兩者的區(qū)別解釋清楚。

有任何意見或建議,或者發(fā)現(xiàn)文中任何問題,歡迎留言!

最后,如果你也對(duì)安卓單元測(cè)試感興趣的話,歡迎加入我們的交流群:

作者 小創(chuàng) 更多文章 | Github | 公眾號(hào)

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/65782.html

相關(guān)文章

  • 安卓單元測(cè)試 - 收藏集 - 掘金

    摘要:?jiǎn)卧獪y(cè)試三單元測(cè)試框架的使用掘金我們寫單元測(cè)試,一般都會(huì)用到一個(gè)或多個(gè)單元測(cè)試框架,在這里,我們介紹一下這個(gè)測(cè)試框架。 Android 單元測(cè)試 (三):JUnit 單元測(cè)試框架的使用 - Android - 掘金 我們寫單元測(cè)試,一般都會(huì)用到一個(gè)或多個(gè)單元測(cè)試框架,在這里,我們介紹一下JUnit4這個(gè)測(cè)試框架。這是Java界用的最廣泛,也是最基礎(chǔ)的一個(gè)框架,其他的很多框架,包括我們后...

    Sunxb 評(píng)論0 收藏0
  • 編寫你的第一個(gè) Android 單元測(cè)試

    摘要:什么是單元測(cè)試單元測(cè)試是對(duì)程序的最小單元進(jìn)行正確性檢驗(yàn)的測(cè)試工作。編寫第一個(gè)單元測(cè)試單元測(cè)試主要使用是測(cè)試框架類庫的擴(kuò)展庫,需要在中聲明測(cè)試依賴。目標(biāo)代碼這里以一個(gè)簡(jiǎn)單的中的例子來說明如何寫單元測(cè)試。TL;DR: 本文主要面向單元測(cè)試新手,首先簡(jiǎn)單介紹了什么是單元測(cè)試,為什么要寫單元測(cè)試,討論了一下 Android 項(xiàng)目中哪些代碼適合做單元測(cè)試,并以一個(gè)簡(jiǎn)單例子演示了如何編寫屬于你的第一個(gè) ...

    番茄西紅柿 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<