Android單元測試(一)

這章就先來說說android中單元測試的操作设哗,簡單走一遍單元測試的流程。
為什么要用到單元測試呢舶胀,一般開發(fā)誰會寫單元測試概说,反正我認識的人都不會做,又耗時間嚣伐,效果又一般糖赔,要是在單元測試的代碼里面又出BUG的話又要改半天,麻煩纤控。
但是有的時候真的是不得不用挂捻,比如說你有一步邏輯操作碉纺,你想去判斷這邏輯操作是否正確船万。但是運行這步操作之前有10步操作,然后這個邏輯操作的情況一共有10種(舉個比較極端的栗子)骨田。那如果你運行Debug檢驗每一種情況的時候耿导,都需要每種情況先執(zhí)行10步操作才能驗證,那就很麻煩啊态贤。

所以這時候你可能就會需要用到單元測試舱呻,直接對單步操作進行測試,也不用把整個項目都跑起來,直接對特定的方法進行測試箱吕。
但說句實在話芥驳,雖然開發(fā)流程中規(guī)定要進行單元測試。但這單元測試誰來做茬高,還不是研發(fā)來做兆旬,我們代碼平時都很趕,還有什么時間去寫單元測試的邏輯和用例怎栽,所以我覺得僅僅對某部分base庫或者重要的邏輯做測試就夠了丽猬。

一.搭建環(huán)境

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

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

版本號肯定不是固定的熏瞄,可以直接在File-Project Structure中查找這個庫脚祟,這樣肯定是最新版本,不過要記得把implementation變成testImplementation 强饮。

然后我們創(chuàng)建相應(yīng)的測試類由桌,也很簡單,以前我是手動創(chuàng)建的胡陪,之前get到別人的一招沥寥。
光標放到你想測的類的類名,然后alt + enter 柠座, 選擇Create Test


自動會幫你填好name邑雅,你想改也行,下面可以選before和after妈经,就是你想在測試前和測試后做的操作的方法淮野。再下面Member可惜選著對應(yīng)的方法。
選擇好之后點擊OK吹泡,然后會讓你選擇androidTest下還是test下骤星,默認創(chuàng)建android項目不是幫你創(chuàng)建3個文件夾嘛

我們因為是只對某個方法做測試,所以選擇test(兩個文件夾的區(qū)別以后再說)爆哑。

二.單元測試

假如我想測一個功能洞难,就測我以前寫的那個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;
}

因為這個是一個很重要的功能揭朝,每個地方的網(wǎng)絡(luò)請求都會走這段代碼队贱,所以我要測試它,看看不同的情況是否能得到我想要的結(jié)果潭袱。

按照上面的做法生成一個測試的類和方法

public class HttpCallBackTest {

    @Test
    public void getDataContent(){
    }

}

可以發(fā)現(xiàn)在androidstudio里面柱嫌,getDataContent方法左邊有個運行按鈕,點擊就可以單獨對這個方法進行測試屯换。

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

 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" +
                "}";

寫個對象來接收

public static class TestData{

        public String id;

        public String sex;

        public int age;

    }

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

    @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);
    }

測試用到的assertEquals方法索守,這個之后會詳細講。

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



如果是代碼錯誤的話也會報出詳細的Exception信息蓝丙。

(2)第二個測試用例

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

(3)第三個測試用例

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

(4)第四個測試用例

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

4個用例如果都通過级遭,說明我這個解析json泛型的方法基本不會有問題。
當然渺尘,可以把4種情況都寫在一起挫鸽,這樣就只用跑一次,我這里是為了看清楚點所有分開寫鸥跟。
這樣就是一個簡單的單元測試的流程丢郊。

三.assert

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



其中 assertThat 是一個比較高級的用法枫匾,這個以后再說,不過我個人基本是沒有用過assertThat 拟淮,單單其它的幾個方法基本就夠用了干茉。

四.補充

可能有的朋友有些時候覺得測一個類難以下手,比如還是我說的解析代碼很泊,你是這樣寫的角虫。

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);
        ......
}

比如這樣,要怎么斷言委造,我這個方法中又不僅僅只有解析的代碼戳鹅,還有其他的代碼,而且我這個方法是一個void方法昏兆,不像上面一樣有返回值的枫虏。

其實很簡單,要不然就判斷這個方法的外層那個方法爬虱,要不然就像我一樣單獨把那塊功能代碼抽出來隶债。我是建議抽出來,也符合單一職權(quán)饮潦。

這篇文章就這樣吧燃异,主要是講講什么時候用到單元測試的心得携狭,然后簡單說一下測試的一個流程继蜡。至于更為復(fù)雜的用法,我自己現(xiàn)在都用不到,如果用上了稀并,以后再講仅颇。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市碘举,隨后出現(xiàn)的幾起案子忘瓦,更是在濱河造成了極大的恐慌,老刑警劉巖引颈,帶你破解...
    沈念sama閱讀 217,185評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件耕皮,死亡現(xiàn)場離奇詭異,居然都是意外死亡蝙场,警方通過查閱死者的電腦和手機凌停,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評論 3 393
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來售滤,“玉大人罚拟,你說我怎么就攤上這事⊥曷幔” “怎么了赐俗?”我有些...
    開封第一講書人閱讀 163,524評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長弊知。 經(jīng)常有香客問我阻逮,道長,這世上最難降的妖魔是什么秩彤? 我笑而不...
    開封第一講書人閱讀 58,339評論 1 293
  • 正文 為了忘掉前任夺鲜,我火速辦了婚禮,結(jié)果婚禮上呐舔,老公的妹妹穿的比我還像新娘币励。我一直安慰自己,他們只是感情好珊拼,可當我...
    茶點故事閱讀 67,387評論 6 391
  • 文/花漫 我一把揭開白布食呻。 她就那樣靜靜地躺著,像睡著了一般澎现。 火紅的嫁衣襯著肌膚如雪仅胞。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,287評論 1 301
  • 那天剑辫,我揣著相機與錄音干旧,去河邊找鬼。 笑死妹蔽,一個胖子當著我的面吹牛椎眯,可吹牛的內(nèi)容都是我干的挠将。 我是一名探鬼主播,決...
    沈念sama閱讀 40,130評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼编整,長吁一口氣:“原來是場噩夢啊……” “哼舔稀!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起掌测,我...
    開封第一講書人閱讀 38,985評論 0 275
  • 序言:老撾萬榮一對情侶失蹤内贮,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后汞斧,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體夜郁,經(jīng)...
    沈念sama閱讀 45,420評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,617評論 3 334
  • 正文 我和宋清朗相戀三年粘勒,在試婚紗的時候發(fā)現(xiàn)自己被綠了拂酣。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,779評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡仲义,死狀恐怖婶熬,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情埃撵,我是刑警寧澤赵颅,帶...
    沈念sama閱讀 35,477評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站暂刘,受9級特大地震影響饺谬,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜谣拣,卻給世界環(huán)境...
    茶點故事閱讀 41,088評論 3 328
  • 文/蒙蒙 一募寨、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧森缠,春花似錦拔鹰、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,716評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至宾茂,卻和暖如春瓷马,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背跨晴。 一陣腳步聲響...
    開封第一講書人閱讀 32,857評論 1 269
  • 我被黑心中介騙來泰國打工欧聘, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人端盆。 一個月前我還...
    沈念sama閱讀 47,876評論 2 370
  • 正文 我出身青樓怀骤,卻偏偏與公主長得像费封,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子晒喷,可洞房花燭夜當晚...
    茶點故事閱讀 44,700評論 2 354

推薦閱讀更多精彩內(nèi)容