Android單元測(cè)試(一)

這章就先來說說android中單元測(cè)試的操作,簡(jiǎn)單走一遍單元測(cè)試的流程。
為什么要用到單元測(cè)試呢,一般開發(fā)誰會(huì)寫單元測(cè)試,反正我認(rèn)識(shí)的人都不會(huì)做,又耗時(shí)間,效果又一般,要是在單元測(cè)試的代碼里面又出BUG的話又要改半天,麻煩。
但是有的時(shí)候真的是不得不用,比如說你有一步邏輯操作,你想去判斷這邏輯操作是否正確。但是運(yùn)行這步操作之前有10步操作,然后這個(gè)邏輯操作的情況一共有10種(舉個(gè)比較極端的栗子)。那如果你運(yùn)行Debug檢驗(yàn)每一種情況的時(shí)候,都需要每種情況先執(zhí)行10步操作才能驗(yàn)證,那就很麻煩啊。

所以這時(shí)候你可能就會(huì)需要用到單元測(cè)試,直接對(duì)單步操作進(jìn)行測(cè)試,也不用把整個(gè)項(xiàng)目都跑起來,直接對(duì)特定的方法進(jìn)行測(cè)試。
但說句實(shí)在話,雖然開發(fā)流程中規(guī)定要進(jìn)行單元測(cè)試。但這單元測(cè)試誰來做,還不是研發(fā)來做,我們代碼平時(shí)都很趕,還有什么時(shí)間去寫單元測(cè)試的邏輯和用例,所以我覺得僅僅對(duì)某部分base庫或者重要的邏輯做測(cè)試就夠了。

一.搭建環(huán)境

搭建環(huán)境很簡(jiǎn)單,在gradle中添加依賴

testImplementation 'org.mockito:mockito-core:2.25.1'

版本號(hào)肯定不是固定的,可以直接在File-Project Structure中查找這個(gè)庫,這樣肯定是最新版本,不過要記得把implementation變成testImplementation 。

然后我們創(chuàng)建相應(yīng)的測(cè)試類,也很簡(jiǎn)單,以前我是手動(dòng)創(chuàng)建的,之前get到別人的一招。
光標(biāo)放到你想測(cè)的類的類名,然后alt + enter , 選擇Create Test


自動(dòng)會(huì)幫你填好name,你想改也行,下面可以選before和after,就是你想在測(cè)試前和測(cè)試后做的操作的方法。再下面Member可惜選著對(duì)應(yīng)的方法。
選擇好之后點(diǎn)擊OK,然后會(huì)讓你選擇androidTest下還是test下,默認(rèn)創(chuàng)建android項(xiàng)目不是幫你創(chuàng)建3個(gè)文件夾嘛

我們因?yàn)槭侵粚?duì)某個(gè)方法做測(cè)試,所以選擇test(兩個(gè)文件夾的區(qū)別以后再說)。

二.單元測(cè)試

假如我想測(cè)一個(gè)功能,就測(cè)我以前寫的那個(gè)Gson解析泛型的功能吧。

    public T getDataContent(String jsondata){
        Gson gson = new Gson();
        
        Type type = getClass().getGenericSuperclass();
        Type[] types = ((ParameterizedType) type).getActualTypeArguments();
        Type ty = new ParameterizedTypeImpl(BaseResponse.class, new Type[]{types[0]});
        BaseResponse<T> data = gson.fromJson(jsondata, ty);
        
        return data.content;
    }

看看BaseResponse

public class BaseResponse<T> {
    public String ret;
    public String msg;
    public T content;
}

因?yàn)檫@個(gè)是一個(gè)很重要的功能,每個(gè)地方的網(wǎng)絡(luò)請(qǐng)求都會(huì)走這段代碼,所以我要測(cè)試它,看看不同的情況是否能得到我想要的結(jié)果。

按照上面的做法生成一個(gè)測(cè)試的類和方法

public class HttpCallBackTest {

    @Test
    public void getDataContent(){
    }

}

可以發(fā)現(xiàn)在androidstudio里面,getDataContent方法左邊有個(gè)運(yùn)行按鈕,點(diǎn)擊就可以單獨(dú)對(duì)這個(gè)方法進(jìn)行測(cè)試。

現(xiàn)在我們要測(cè)試這個(gè)功能,那么就需要寫測(cè)試用例,假如我這邊寫4個(gè)測(cè)試用例看看能不能都成功解析,4個(gè)json字符串(在代碼里面加了換行符所以可能有點(diǎn)難看)。

 String mockData = "{\n" +
                "\t\"ret\":\"1\",\n" +
                "\t\"msg\":\"success\",\n" +
                "\t\"content\":{\n" +
                "\t\t\"id\":\"10000\",\n" +
                "\t\t\"sex\":\"男\(zhòng)",\n" +
                "\t\t\"age\":18\n" +
                "\t}\n" +
                "}";

String mockData2 = "{\n" +
                "\t\"ret\":\"1\",\n" +
                "\t\"msg\":\"success\",\n" +
                "\t\"content\":[\n" +
                "\t\t{\n" +
                "\t\t\t\"id\":\"10000\",\n" +
                "\t\t\t\"sex\":\"男\(zhòng)",\n" +
                "\t\t\t\"age\":\"18\"\n" +
                "\t\t},\n" +
                "\t\t{\n" +
                "\t\t\t\"id\":\"10001\",\n" +
                "\t\t\t\"sex\":\"女\",\n" +
                "\t\t\t\"age\":\"16\"\n" +
                "\t\t}\n" +
                "\t]\n" +
                "}";

 String mockData3 = "{\n" +
                "\t\"ret\":\"1\",\n" +
                "\t\"msg\":\"success\",\n" +
                "\t\"content\": \"aaa\"\n" +
                "}";

 String mockData4 = "{\n" +
                "\t\"ret\":\"1\",\n" +
                "\t\"msg\":\"success\",\n" +
                "\t\"content\": []\n" +
                "}";

寫個(gè)對(duì)象來接收

public static class TestData{

        public String id;

        public String sex;

        public int age;

    }

現(xiàn)在來寫測(cè)試的代碼
(1)第一個(gè)測(cè)試用例

    @Test
    public void getDataContent(){
        httpCallBack = new HttpCallBack<TestData>();
     
        TestData testData = (TestData) httpCallBack .getDataContent(mockData);

        assertEquals("10000",testData.id);
        assertEquals("男",testData.sex);
        assertEquals(18,testData.age);
    }

測(cè)試用到的assertEquals方法,這個(gè)之后會(huì)詳細(xì)講。

可以看到下邊會(huì)有打印 Process finished with exit code 0 說明測(cè)試通過,如果不通過會(huì)顯示詳細(xì)的不通過的信息。
比如說我寫的 assertEquals(12,testData.age); ,錯(cuò)誤的情況會(huì)提示



如果是代碼錯(cuò)誤的話也會(huì)報(bào)出詳細(xì)的Exception信息。

(2)第二個(gè)測(cè)試用例

    @Test
    public void getDataContent(){
        httpCallBack = new HttpCallBack<Lits<TestData>>();
        Lits<TestData> testDatas = (Lits<TestData>) httpCallBack .getDataContent(mockData2);
        assertEquals("女",testDatas.get(1).sex);
    }

(3)第三個(gè)測(cè)試用例

    @Test
    public void getDataContent(){
        httpCallBack = new HttpCallBack<String>();
        String testData = (String ) httpCallBack .getDataContent(mockData3);
        assertEquals("aaa",testData);
    }

(4)第四個(gè)測(cè)試用例

    @Test
    public void getDataContent(){
        httpCallBack = new HttpCallBack<Lits<TestData>>();
        Lits<TestData> testDatas = (Lits<TestData>) httpCallBack .getDataContent(mockData4);
        assertEquals(0,testDatas.size());
    }

4個(gè)用例如果都通過,說明我這個(gè)解析json泛型的方法基本不會(huì)有問題。
當(dāng)然,可以把4種情況都寫在一起,這樣就只用跑一次,我這里是為了看清楚點(diǎn)所有分開寫。
這樣就是一個(gè)簡(jiǎn)單的單元測(cè)試的流程。

三.assert

從上面可以看出最主要判斷測(cè)試正確和錯(cuò)誤的方法是用assert(斷言)。
而這些方法都是屬于Assert類,大概的斷言方法有這些



其中 assertThat 是一個(gè)比較高級(jí)的用法,這個(gè)以后再說,不過我個(gè)人基本是沒有用過assertThat ,單單其它的幾個(gè)方法基本就夠用了。

四.補(bǔ)充

可能有的朋友有些時(shí)候覺得測(cè)一個(gè)類難以下手,比如還是我說的解析代碼,你是這樣寫的。

public void requestFinish(String jsonData){
        ......
        ......

        Gson gson = new Gson();
        Type type = getClass().getGenericSuperclass();
        Type[] types = ((ParameterizedType) type).getActualTypeArguments();
        Type ty = new ParameterizedTypeImpl(BaseResponse.class, new Type[]{types[0]});
        BaseResponse<T> data = gson.fromJson(jsondata, ty);
        
        // 假如用回調(diào)的方式
        callback.finish(data.content);
        ......
}

比如這樣,要怎么斷言,我這個(gè)方法中又不僅僅只有解析的代碼,還有其他的代碼,而且我這個(gè)方法是一個(gè)void方法,不像上面一樣有返回值的。

其實(shí)很簡(jiǎn)單,要不然就判斷這個(gè)方法的外層那個(gè)方法,要不然就像我一樣單獨(dú)把那塊功能代碼抽出來。我是建議抽出來,也符合單一職權(quán)。

這篇文章就這樣吧,主要是講講什么時(shí)候用到單元測(cè)試的心得,然后簡(jiǎn)單說一下測(cè)試的一個(gè)流程。至于更為復(fù)雜的用法,我自己現(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),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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