做開發這么長時間了,對app測試一直沒有深入研究過。平時開發完后,都是自己根據原型操作一下,沒有太大問題就交給其他人測試了,現在要專門研究一下測試這塊的東西,包括自動化測試、單元測試等方面 。
使用Android Studio進行單元測試
android studio的單元測試由于只是模擬android開發環境,但是其不是真正的android開發環境,所以不能測試UI功能,不能測試需要硬件支持的功能(比如藍牙,wifi等),不能測試App跳轉等等,那么其可以測試那些內容呢?
- 測試一些數據性的功能,比如加載網絡數據
- 測試SharedPerferences,測試數據庫,測試函數等
- 工具類的測試,比如驗證時間,轉化格式,正則驗證等等
在Android Studio中進行單元測試并不需要什么插件或者過多的配置,Android Studio本身就集成了測試環境,無論是單純的java代碼單元測試還是依賴Android SDK的Android代碼單元測試都可以。
Android單元測試框架主要有:JUnit和Robolectric,本文就不詳細介紹。
1. 使用JUnit進行單元測試
參考:http://www.open-open.com/lib/view/open1328152424546.html
2. Robolectric
http://robolectric.org/getting-started/
在安卓模擬器或者真機上跑測試用例速度很慢。構建、部署、啟動app,通常需要花費很久。Robolectric提供一種更好的方式,它模擬了android sdk中的jar包,可以直接在jvm中運行測試用例,這樣就大大節省了時間。
另外,使用JUnit對fragment進行單元測試,可以參考該文章:http://blog.denevell.org/android-testing-fragments.html
首先我們需要明確安卓的單元測試主要分為兩種類型:
- 在開發主機Java虛擬機上運行的Junit Test
- 在Android真機或者虛擬機上運行的Instrumented unit tests
因為Junit Test免去了將apk包安裝到android設備上的步驟,因此速度上會比Instrumented unit tests快很多。但是跟android相關的一些庫只能運行在android設備上,而無法再本機Java虛擬機上運行,比如很多包名中帶android的庫。因此我們這里需要做一個選擇,如果某些類沒有用到android相關的庫,則完全可以使用Junit Test,加快測試速率。
我們新創建一個工程后,項目在Android Studio的Project中應該是這樣的,其中androidTest包中存放的是Instrumented unit tests的文件,而test中則是Junit Test,這兩個文件夾在項目創建的時候AS都會幫我們創建好:
分析一下:
(1)androidTest這個文件夾里的測試類主要是對android的例子進行單元測試。需要運行于設備之上。
(2)test這個文件夾的測試類主要對java的例子進行單元測試,無需運行于設備之上。
在你的gradle中加入Junit的依賴,注意這里的依賴方式是測試期間的依賴(testCompile)
testCompile 'junit:junit:4.12'
編寫java測試用例
如果所寫的測試代碼沒有使用android sdk(android.***下的代碼),那么可以在test目錄下新建,本例中即為ExampleUnitTes
注意測試用例即一個public void的方法,并且加上@Test注解,這是Junit的標準用法
public class ExampleUnitTest {
@Test
public void addition_isCorrect() throws Exception {
assertEquals(4, 2 + 2);
}
}
編寫好測試代碼后,有如下兩種方法運行
成功的例子
失敗的例子
還有一種失敗的情況 ,因為用了Android的代碼,所以這樣子了,這就引出我們的Android測試例子。
編寫Android測試用例
/**
* Created by dell on 2017/1/18.
*
* 測試用例類需要使用注解:@MediumTest和@RunWith(AndroidJUnit4.class)
*/
@MediumTest
@RunWith(AndroidJUnit4.class)
public class MTest {
/**
*
* 我們在編寫測試函數的時候需要注意兩點:
測試函數需要為public
測試函數需要添加@Test注解
*/
@Test
public void test1() {
// Context of the app under test.
Context appContext = InstrumentationRegistry.getTargetContext();
assertEquals("uuch.com.android_activityanim", appContext.getPackageName());
Log.i("tag", "$");
assertEquals("result:", 123, 100 + 33);
}
}
運行方式和以上 java測試用例一樣。
常見的單元測試框架
JUnit4
這是Java界用的最廣泛,也是最基礎的一個框架 。在Android項目里面使用JUnit是很簡單的,你只需要將JUnit這個library加到你的dependencies里面。
testCompile 'junit:junit:4.12'
如果你通過AndroidStudio創建一個項目,這個dependency默認是加上了的,所以你甚至這步都可以省略。
上面java測試用例就是用得這個框架,相對來說是比較簡單,也是比較容易理解的 。其中Assert部分,可以幫我們驗證一個方法的返回結果。然而,這些只能幫我們測試有返回值的那些方法;沒有返回值的方法,即void方法,則要通過另外一個框架,Mockito,來驗證它的正確性
Mockito
這個是Java界使用最廣泛的一個mock框架。
Robolectric3.0
官網地址
Github地址
Robolectric環境搭建(Android Studio + Gradle)
Android 單元測試--Robolectric
Instrumentation與Roboletric都是針對 Android 進行單元測試的框架,前者在執行 case 時候是以 Android JUnit 的方式運行,因此必須在真實的 Android 環境中運行(模擬器或者真機),而后者則是以 Java Junit 的方式運行,這里就脫離了對 Android 環境的依賴,而可以直接將 case 在 JVM 中運行,大贊,因此很適合將 Roboletric 用于 Android 的測試驅動開發。
官網介紹
Running tests on an Android emulator or device is slow! Building, deploying, and launching the app often takes a minute or more. That’s no way to do TDD. There must be a better way.
Wouldn’t it be nice to run your Android tests directly from inside your IDE? Perhaps you’ve tried, and been thwarted by the dreaded java.lang.RuntimeException: Stub!?
Robolectric is a unit test framework that de-fangs the Android SDK jar so you can test-drive the development of your Android app. Tests run inside the JVM on your workstation in seconds. With Robolectric you can write tests like this:
對于Android app來說,寫起單元測試來瞻前顧后,一方面單元測試需要運行在模擬器上或者真機上,麻煩而且緩慢,另一方面,一些依賴Android SDK的對象(如Activity,TextView等)的測試非常頭疼,Robolectric可以解決此類問題,它的設計思路便是通過實現一套JVM能運行的Android代碼,從而做到脫離Android環境進行測試。
使用
在app/gradle中加入依賴關系
dependencies {
testCompile "org.robolectric:robolectric:3.2.2"
}
在app/src/test 目錄下,創建測試用例 ,運行方式和上面的一樣, 第一次會比較慢
@RunWith(RobolectricTestRunner.class)
@Config(constants = BuildConfig.class,sdk = 19)
public class JustTest {
@Before
public void setUp() throws URISyntaxException {
//輸出日志
ShadowLog.stream = System.out;
}
@Test
public void testActivity() {
MainActivity sampleActivity = Robolectric.setupActivity(MainActivity.class);//創建Activity
Log.i("","_____________" + sampleActivity.getClass().getSimpleName());
Assert.assertNotNull(sampleActivity);//判斷是否為空
Assert.assertEquals(sampleActivity.getClass().getSimpleName(), "MainActivity");//獲取Activity的標題
}
}
如果想要支持Fragment
// 如果使用support的Fragment,需添加以下依賴
testCompile 'org.robolectric:shadows-support-v4:3.1.2'
shadow-support包提供了將Fragment主動添加到Activity中的方法:SupportFragmentTestUtil.startFragment(),簡易的測試代碼如下
Instrumentation
Instrumentation框架主要是依靠控件的ID來進行定位的,擁有成熟的用例管理系統,是Android主推的白盒測試框架。若想對項目進行深入的、系統的單元測試,基本上都離不開Instrumentation這把屠龍寶刀。
參考文檔
Android單元測試框架Robolectric3.0介紹(一)
使用強大的 Mockito 測試框架來測試你的代碼
FaceBook 開源的一個測試網絡訪問速度的庫,適用于安卓 APP
Android Espresso 測試框架介紹
在Android Studio中進行單元測試和UI測試
Android單元測試研究與實踐
Android developer 測試支持庫
要了解android單元測試,首先必須了解junit
Android單元測試框架Robolectric3.0介紹(一)
關于安卓單元測試,你需要知道的一切