這章就先來說說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)在都用不到,如果用上了稀并,以后再講仅颇。