初入Android單元測試
前言
在今年的Android開發技術中,MVP & RxJava & Retrofit 已經成為各個項目的標配了。了解過MVP的人都知道,其中的一個優點就是便于 單元測試 的編寫。那么我們今天就步入單元測試的這個深坑吧。
單元測試是什么
單元測試(unit testing),是指對軟件中的最小可測試單元進行檢查和驗證。對于單元測試中單元的含義,一般來說,要根據實際情況去判定其具體含義,如C語言中單元指一個函數,Java里單元指一個類,圖形化的軟件中可以指一個窗口或一個菜單等。總的來說,單元就是人為規定的最小的被測功能模塊。單元測試是在軟件開發過程中要進行的最低級別的測試活動,軟件的獨立單元將在與程序的其他部分相隔離的情況下進行測試。
其實很容易理解,對于我們開發者來說就是驗證一個功能是否正確的一個過程。
為什么要寫單元測試
相信很多東西都有自己的測試人員,所以有的人就會問了。為什么我們開發者還需要自己寫代碼來進行測試呢?
首先我們要知道,單元測試一般是開發人員最應該關注的事情之一,單元測試只是測試一個方法單元, 他不是測試整個流程沒有問題。引入單元測試,帶來的好處是顯而易見的,首先可以直接幫我們尋找出 bug,并且在加入新的功能模塊時,可以發現它是否影響并破壞了我們原有的功能。單元測試還可以強迫讓我們的代碼變得精煉短小,因為太過復雜的代碼無法引入單元測試。單元測試還可以節省測試成本,不需要啟動整個系統,就可以直接的,針對性的對任意模塊進行測試。而且可以簡單的模擬各種情況覆蓋其各種分支。這是降低整體開發時間,提高軟件質量的一種有效方法。
當然單元測試不僅需要學習,而且你要學習的東西還真不少,你要學習 JUnit 的使用,你要學習 Mokito 的使用, Robolectric 的使用, 依賴注入 的概念和使用等等等。
簡單的單元測試
單元測試其實并沒有你想象中的那么復雜。
我們先用Java來舉例看一下就知道了,
// 這是一個普通的類
public class Calculator {
public int add(int one, int another) {
// 為了簡單起見,暫不考慮溢出等情況。
return one + another;
}
public int multiply(int one, int another) {
// 為了簡單起見,暫不考慮溢出等情況。
return one * another;
}
}</code></pre>
// 這是對應的測試代碼
public class CalculatorTest {
public static void main(String[] args) {
Calculator calculator = new Calculator();
int sum = calculator.add(1, 2);
if(sum == 3) {
System.out.println("add() works!")
} else {
System.out.println("add() does not works!")
}
int product = calculator.multiply(2, 4);
if (product == 8) {
System.out.println("multiply() works!")
} else {
System.out.println("multiply() does not works!")
}
}
}</code></pre>
也許這個示例比較簡單,讓你覺得這個測試代碼反而很多余了。如果你的類中方法一旦變多變復雜了,這樣的測試就顯得很重要了。當然也有人會說,我自己寫那么多判斷的代碼,然后還要在看著terminal的輸出,才知道測試是通過還是失敗。同時,也有人會問,我們Android中,很多方法也都沒有返回值啊,我們應該怎么測呢?
這些一切的一切,都由框架來替我們解決了,所以我們應該掌握幾個單元測試的框架。
有哪些單元測試框架
測試是一個比較大的東西,對于Android而言,有UI測試,功能測試,集成測試,扒拉扒拉扒拉的很多,當然也有很多的測試方法。今天我們就先來看看有哪些測試的方法或者說是測試框架:
JUnit :能夠直接在PC上執行;
Mokito
Robolectric :在不需要依賴Android環境的前提下,實現在PC上直接運行Android的單元測試;
Robotium :第三方UI測試框架;
Espresso :Google推出的測試框架;
UI Automator :流程的UI測試框架;
在此我列舉的也只是部分常用的第三方測試框架,但是不要急著就去學習它們了。我們應該先來了解一些基本的概念,這樣才能更好的掌握理解框架。
Mock
一個類的方法可以分為兩種,一種是有返回值的,另一種是沒有返回值的。對于有返回值的方法,我們要測起來比較容易,就跟上面的 Calculator 例子那樣,輸入相應的參數,得到相應的返回值,然后驗證得到的返回值跟我們預期的值一樣,就好了。
但是沒有返回值的方法,要怎么測試呢?
這里我們就以Android中的一個login流程來進行分析一下:
// 一個Login頁面,上面有兩個輸入框和一個button。兩個輸入框分別用于輸入用戶名和密碼。點擊button以后,有一個UserManager會去執行performlogin操作,然后將結果返回,更新頁面。
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);
}</code></pre>
這個方法是void的,那么怎么驗證這個方法是正確的呢?其實仔細想想,這個方法也是有輸出的,它的輸出就是,調用了mUserManager的performLogin方法,同時傳給他兩個參數。所以只要驗證mUserManager
的performLogin方法得到了調用,同時傳給他的參數是正確的,就說明這個方法是能正常工作的。
那怎么樣驗證這個Activity的login()方法,會調用mUserManager的performLogin方法呢?這里涉及到 mock 的概念,所以我們就先來講講什么是 Mock
所謂的 Mock 就是創建一個類的虛假的對象,在測試環境中,用來替換掉真實的對象,主要提供兩大功能:
- 驗證這個對象的某些方法的調用情況,調用了多少次,參數是什么等等
- 指定這個對象的某些方法的行為,返回特定的值,或者是執行特定的動作
要使用 Mock,一般需要用到 Mock 框架,常見的就是 Mockito 這個框架,這個是Java界使用最廣泛的一個mock框架。
小結
本篇文章,從為什么要做單元測試到單元測試所涉及的一些概念,框架進行了介紹。同時引入了Mockito這個框架,但是這個框架的使用也不是一兩句話就可以介紹清楚的,所以打算在下一篇文章對Mockito的使用進行進一步的講解。
來自:http://www.jianshu.com/p/78a67817ee5a