單元測試是開發(fā)人員需要自己完成的一個測試,可能有時候我們會覺得寫測試會特別費時間,畢竟代碼寫下去并運行后我們還是可以保證它的正確性的。但是當項目被頻繁的修改的時候就會有很多莫名奇妙的 bug 冒出來了,定位一個 bug 至少都需要經(jīng)歷重新編譯一次程序然后再安裝到手機上并重現(xiàn) bug 的場景的流程,因此適當?shù)膶懸恍﹩卧獪y試還是可以節(jié)省調(diào)試時間的。
什么是單元測試
- 跟普通的代碼相比,它是驗證代碼正確性的代碼。
- 它是由開發(fā)人員自己編寫的測試代碼。
- 單元測試可便于后期的重構(gòu)和維護
- 可優(yōu)化設(shè)計,單元測試能使開發(fā)人員的代碼便于測試的方向優(yōu)化,解除軟件中的耦合。
- 單元測試也是一種特殊的文檔,它可展示函數(shù)或則類如何使用。
Android Studio 中生成好的單元測試
我們在 AS 新建的工程都會默認含有存放測試文件的包

簡單的看下 ExampleUnitTest 文件里的代碼
public class ExampleUnitTest {
@Test
public void addition_isCorrect() {
assertEquals(4, 2 + 2);
}
}
從以上代碼就可以猜出 assertEquals 方法的作用就是用來判斷其所傳入的兩個參數(shù)是否相等的,運行只需右鍵點擊 run ,就可以得到一個結(jié)果,而這些都是毫秒級別的操作。

如何編寫單元測試
在 Android 中雖然有很多的測試優(yōu)秀的測試框架來替代 Junit ,但是由于 Junit 的簡單性以及基礎(chǔ)性,所以還是得先了解它再去學別的好一些,接下來看一個簡單的例子 。
/**
* 加法的接口
*/
public interface Adder {
public int add (int a, int b);
}
/**
* 加法實現(xiàn)類
*/
public class AdderImpl implements Adder {
@Override
public int add(int a, int b) {
return a + b;
}
}
選擇對應的類,將光標停留在類名上,按下 ALT + ENTER ,在彈出的彈窗中選擇Create Test 勾上圖中的選項,就可生成一個文件。


我們在 setUp 函數(shù)初始化對象,在 tearDown 函數(shù)銷毀對象,在 add 方法里測試該對象方法的正確性。
package cn.demon96.testandroidtest;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.*;
public class AdderImplTest {
Adder mAdder;
@Before
public void setUp() throws Exception {
mAdder = new AdderImpl();
}
@After
public void tearDown() throws Exception {
mAdder = null;
}
@Test
public void add() {
assertEquals(0, mAdder.add(0,0));
assertEquals(1, mAdder.add(-1,2));
assertEquals(Integer.MAX_VALUE + 1, mAdder.add(Integer.MAX_VALUE,1));
}
}
通過以上簡單的操作,在一些重要的方法中適當?shù)氖褂脝卧獪y試就可以在代碼經(jīng)過大量的修改的情況下只需要運行一下測試用例就可以在幾秒中的時間里發(fā)現(xiàn)問題。
運行多個測試用例
當測試類多了的時候一個一個的運行反而會更浪費時間,這時候可以將測試類分組進行統(tǒng)一的運行,運行多個測試類用到的是 TestSuite 類,此類有兩種用法。
- 用法一:使用
JUnit4TestAdapter包裝測試類
package cn.demon96.testandroidtest;
import junit.framework.JUnit4TestAdapter;
import junit.framework.Test;
import junit.framework.TestSuite;
public class MainTest {
public static Test suite() {
TestSuite suite = new TestSuite("cn.demon96.testandroidtest");
suite.addTest(new JUnit4TestAdapter(AdderImplTest.class));
suite.addTest(new JUnit4TestAdapter(ExampleUnitTest.class));
return suite;
}
}
- 用法二:使用注解
package cn.demon96.testandroidtest;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
@RunWith(Suite.class)
@Suite.SuiteClasses({
AdderImplTest.class,
ExampleUnitTest.class,
})
public class MainTest {
}
Junit 簡介
Junit 是基于 java 語言的單元測試框架,已默認配置在安卓項目中。
testImplementation 'junit:junit:4.12'
- 使用時的注意事項
- 測試的方法應該是
public的 - 可選用
setUp進行初始化工作, 使用tearDown進行收尾工作。 - 每個測試方法沒有關(guān)聯(lián),執(zhí)行的順序也不一定是代碼中的順序,因此測試方法之間不要存在有依賴性。
- Junit 的斷言和失敗提示
是否相等 assertEquals
assertEquals(0, 0);是否為真 assertTrue
assertTrue(true);是否為空 assertNull
assertNull(null);是否為同一個對象 assertSame
String s1 = "123";
String s2 = s1;
assertSame(s1, s2);
- 失敗提示
assertNull("這個不是空的!", new Object());
更詳細的用法可以看 Assert 類的源碼。
測試哪些內(nèi)容
- 邊界條件
- 覆蓋執(zhí)行路徑
參考
- 《Android 開發(fā)進階 從小工到專家》何紅輝