編輯:關於Android編程
介紹Robolectric主要從框架簡介、框架優點、框架可行性分析,框架環境配置、框架演示、框架參考資料方面進行介紹:
一、框架簡介
官網的介紹
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環境進行測試。
1、可以不運行於設備之上,可以想一想,一個項目小點還好,大一點的項目跑起來平時花費我們兩三分鐘,所以不錯哦。
2、使用Android的例子測試大多拋出java.lang.RuntimeException: Stub!?這個出錯信息,白了還是個運行的過程,所以如果你的unit test代碼裡面有android。
二、框架優點
在安卓模擬器或者真機上跑測試用例速度很慢。構建、部署、啟動app,通常需要花費一分鐘或者更久。這不是TDD(測試驅動開發)模式.Robolectric提供一種更好的方式。
可能你一直嘗試在java IDE中使用junit或者testng直接跑測試用例,但是一直報java.lang.RuntimeException: Stub!異常。
這個異常是因為在jdk中沒有android運行環境。而現在Robolectric這款android單元測試工具,模擬了android sdk中的jar包,可以直接在jvm中運行測試用例,這樣就大大節省了時間。
Robolectric可以處理控件展示、資源加載和很多使用native C實現的真機上的其他功能。所以我們可以使用Robolectric來模擬真機上的大部分操作。我們可以很方便地獲取Robolectric的源碼,直接查看它的模擬機制,所以使用Robolectric,我們也可以模擬錯誤條件和一些真實的傳感器信號。
Robolectric允許我們在項目工程中或者持續集成(CI如hudson、jenkins)中使用jvm來執行測試用例,所以就省掉了打包、安裝的過程,將測試用例的執行時間由分鐘級降到秒級。
對比:
三、可行性分析
(1)環境配置相對簡單(根據後面介紹配置即可)
(2)可以直接在jvm中運行測試用例(包含Android相關類,打印日志等),這樣就大大節省了時間。
(3)Robolectric可以在持續集成(jenkins)中使用jvm來執行測試用例。
(4)Robolectric可以對(OrmLite,retrofit)網絡請求,數據庫進行測試。
(5)Robolectric相對比較成熟,使用起來簡單,官網有詳細的API文檔,一些難點與資料比較容易查找。
但是存在一些問題,
(1)只支持22版本以及以下,我測試了23,22,21,20,19。其中20,23不支持。(第一次運行測試自動下載一些Jar包)
(2)異步測試出現一些問題(比如改變一些編碼習慣,比如回調函數不能寫成匿名內部類對象,需要定義一個全局變量,並破壞其封裝性,即提供一個get方法,供UT調用),解決方案使用Mockito來結合進行測試,將異步轉為同步,後面參考資料有。
(3)遇到問題,作者很積極回答,詳情https://github.com/robolectric/robolectric/issues
四、框架環境配置
一、Gradle配置
在build.gradle中配置如下依賴關系:
二、在test目錄(如木有自己創建)
建立一個JustTest測試類
三、通過注解配置JustTest(測試類)
@RunWith(RobolectricGradleTestRunner.class) @Config(constants = BuildConfig.class,sdk = 19) public class JustTest {請注意:sdk目前只適配(API21以及以下,可選擇21,19,16)
2、working directory 設置為$MODULE_DIR$
如果在測試過程遇見如下問題,解決的方式就是設置working directory的值:
java.io.FileNotFoundException: build\intermediates\bundles\debug\AndroidManifest.xml (系統找不到指定的路徑。)設置方法如下圖所示:
configurations
Working directory的配置
五、框架演示
Android 打印的日志輕松可以在控制台查看
@Before public void setUp() throws URISyntaxException { //輸出日志 ShadowLog.stream = System.out; }
寫了一個創建Activity實例、Activity的跳轉,生命周期的測試,UI組件狀態,Toast信息驗證的測試用例
//創建Activity實例 @Test public void testActivity() { MainActivity sampleActivity = Robolectric.setupActivity(MainActivity.class);//創建Activity Assert.assertNotNull(sampleActivity);//判斷是否為空 Assert.assertEquals(sampleActivity.getTitle(), "MainActivity");//獲取Activity的標題 } /* @Test public void testMainActivity() { MainActivity mainActivity = Robolectric.setupActivity(MainActivity.class);//創建Activity mainActivity.findViewById(R.id.tv_test).performClick();//自動點擊按鈕 ShadowActivity shadowActivity = Shadows.shadowOf(mainActivity);//ShodawRobolectric的本質是在Java運行環境下, // 采用Shadow的方式對Android中的組件進行模擬測試,從而實現Android單元測試。對於一些Robolectirc暫不支持的組件,可以采用自定義Shadow的方式擴展Robolectric的功能。 Intent expectedIntent = new Intent(mainActivity, TestActivity.class); Intent actualIntent = shadowActivity.getNextStartedActivity(); Assert.assertEquals(expectedIntent, actualIntent); String hello = mainActivity.getResources().getString(R.string.app_name); Assert.assertEquals("My Application",hello); }*///這個網上很多人寫這個,我驗證是錯誤的。 /** * 測試下一個Activity */ @Test public void testNextActivity(){ MainActivity mainActivity = Robolectric.setupActivity(MainActivity.class); mainActivity.findViewById(R.id.tv_test).performClick(); ShadowActivity shadowActivity = Shadows.shadowOf(mainActivity); Intent nextStartedActivity = shadowActivity.getNextStartedActivity(); ShadowIntent shadowIntent = Shadows.shadowOf(nextStartedActivity); Assert.assertEquals( shadowIntent.getIntentClass(), (TestActivity.class)); } //測試生命周期 @Test public void testLifecycle() { ActivityController點擊右鍵,運行,注意第一次運行需要下載一些東西,所以很慢,最好翻牆或者設置代理activityController = Robolectric.buildActivity(MainActivity.class).create().start(); Activity activity = activityController.get(); TextView textview = (TextView) activity.findViewById(R.id.tv_test); Assert.assertEquals("onCreate",textview.getText().toString()); activityController.resume(); Assert.assertEquals("onResume", textview.getText().toString()); activityController.destroy(); Assert.assertEquals("onDestroy", textview.getText().toString()); } //UI組件狀態 @Test public void testViewState(){ MainActivity mainActivity = Robolectric.setupActivity(MainActivity.class); CheckBox checkBox = (CheckBox) mainActivity.findViewById(R.id.box_test); Button testBt = (Button) mainActivity.findViewById(R.id.bt_test); Assert.assertTrue(testBt.isEnabled()); checkBox.setChecked(true); //點擊按鈕,CheckBox反選 testBt.performClick(); Assert.assertTrue(!checkBox.isChecked()); testBt.performClick(); Assert.assertTrue(checkBox.isChecked()); } //Toast @Test public void testToast(){ //點擊按鈕,出現吐司 MainActivity mainActivity = Robolectric.setupActivity(MainActivity.class); Button toastBt = (Button) mainActivity.findViewById(R.id.bt_toast); toastBt.performClick(); Assert.assertEquals(ShadowToast.getTextOfLatestToast(),"we love UT"); }
運行結果(成功)如下:
弄個失敗的例子,改了下一個Activity的跳轉,將TestActivity改成SecondActivity.代碼與運行結果如下:
運行結果顯示有錯誤,具體到行數與差異之處。
代碼地址:http://pan.baidu.com/s/1c2E4BUo
安卓手機QQ自帶截圖功能,iPad、iPhone則需要使用iOS系統自帶的截圖方法或者第三方APP。下面就隨小編分別來看看,安卓手機QQ和iOS系統的ipa
廢話不多說了,直接給大家貼代碼了。package com.example.testactivityresquest; import android.app.Activit
今天和大家分享一下Android中Matrix的簡單用法,Matrix其實就是一個3*3的矩陣,利用這個矩陣對圖像操作。在Android中,為我們提供一些封裝好的方法可以
第1節 Broadcast Receiver概述很多時候,我們希望一個應用程序在它沒有運行起來的時候,也能感知系統狀態的某些變化,如果條件合適,就讓這個應用就運行起來。比