Build Instrumented Test

Setups

Instrumented Test是基于JUnit的,使用JUnit4的Test Class風(fēng)格我們可以可以很快的寫(xiě)出Instrumented Test Class。當(dāng)然在此之前结序,我們還需要做一些環(huán)境的配置工作。包括:

  • 配置 instrumentation runner刚盈。這個(gè)runner負(fù)責(zé)執(zhí)行Instrumented Test Class仪糖!
    android {
          defaultConfig {
              ...
              testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
            }
      }
    
  • 配置需要的dependencies,這里將需要的依賴都列出來(lái)了忙上,包括基本依賴拷呆、UI測(cè)試的依賴和其他庫(kù)。
    dependencies {
      //這個(gè)庫(kù)是為了避免因?yàn)橹鞒绦蛞蕾嚵讼嗤瑤?kù)的不同版本導(dǎo)致沖突加入的
      androidTestCompile 'com.android.support:support-annotations:24.0.0'
      //必需的依賴疫粥;
      androidTestCompile 'com.android.support.test:runner:0.5'
      //可選依賴茬斧,包含Android提供的幾個(gè)Rule實(shí)現(xiàn),如ActivityTestRule梗逮,ServiceTestRule
      androidTestCompile 'com.android.support.test:rules:0.5'
      // 可選-- Hamcrest library项秉,matcher庫(kù),可以很方便的構(gòu)建matcher
      androidTestCompile 'org.hamcrest:hamcrest-library:1.3'
      // 可選-- UI testing with Espresso UI測(cè)試時(shí)使用
      androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.2'
      // 可選 -- UI testing with UI Automator 跨App UI測(cè)試時(shí)使用
      androidTestCompile 'com.android.support.test.uiautomator:uiautomator-v18:2.1.2'
    

}


##Test UI
主要是使用Espresso庫(kù)來(lái)進(jìn)行UI測(cè)試慷彤。Espresso能夠自動(dòng)test action和target app的UI狀態(tài)娄蔼,它會(huì)在UI線程Idle的時(shí)候去執(zhí)行test code,避免開(kāi)發(fā)者自己去做同步的工作瞬欧,提高了測(cè)試的可靠性贷屎。在進(jìn)行UI測(cè)試時(shí),可能需要在開(kāi)發(fā)者選項(xiàng)中將窗口動(dòng)畫(huà)縮放艘虎、過(guò)渡動(dòng)畫(huà)縮放和動(dòng)畫(huà)時(shí)長(zhǎng)調(diào)整選項(xiàng)關(guān)閉唉侄,否則可能會(huì)導(dǎo)致不可預(yù)料的結(jié)果或者直接導(dǎo)致測(cè)試失敗。Espresso的使用主要分為幾個(gè)步驟:
1. 使用`onView()`或者`onData()`方法(針對(duì)AdapterView)找到對(duì)應(yīng)的view野建。`onView()`方法接收一個(gè)`Matcher<View>`對(duì)象作為參數(shù)用來(lái)在當(dāng)前的視圖層次結(jié)構(gòu)中找到對(duì)應(yīng)的view属划,找不到或者有多個(gè)View滿足條件都會(huì)拋出異常『蛏可以查看 [ViewMatchers](https://developer.android.com/reference/android/support/test/espresso/matcher/ViewMatchers.html) 看看Espresso提供的matchers同眯。`onData()`主要適用于AdapterView,比如ListView唯鸭、GridView须蜗、Spinner。這些控件可能包含很多的item view目溉,使用`onView()`方法去找明肮,不一定能找到,因?yàn)閕tem view可能不在當(dāng)前視圖層次結(jié)構(gòu)中顯示缭付。所以espresso提供`onData()`方法使用柿估。該方法接收一個(gè)`Matcher<Object>`類(lèi)型的參數(shù)用來(lái)匹配對(duì)應(yīng)的Item。其實(shí)就是在對(duì)應(yīng)的Adapter上調(diào)用`getItem()`方法陷猫,用返回的Object對(duì)象去匹配那個(gè)Matcher對(duì)象秫舌。找到這個(gè)Item的妖,espresso會(huì)自動(dòng)滾動(dòng)到該item的位置。
```java
onView(withText("Sign-in"));
onView(withId(R.id.button_signin));
onView(allOf(withId(R.id.button_signin), withText("Sign-in")));

onData(allOf(is(instanceOf(Map.class)),
      hasEntry(equalTo(LongListActivity.ROW_TEXT), is(str))));
  1. 通過(guò)上面兩個(gè)方法的返回對(duì)View進(jìn)行操作足陨。onView()方法會(huì)返回一個(gè)ViewInteraction對(duì)象嫂粟,而onData()方法返回一個(gè)DataInteraction對(duì)象。兩個(gè)對(duì)象都有一個(gè)perform()方法钠右,該方法接收變長(zhǎng)的ViewAction對(duì)象作為參數(shù)赋元,可以連續(xù)執(zhí)行一些的操作,諸如點(diǎn)擊飒房、滑動(dòng)搁凸、輸入等操作。具體可執(zhí)行的操作由具體的view決定狠毯,查看 ViewActions看看可使用什么操作护糖。
  2. ViewInteraction或者DataInteraction上調(diào)用check()方法驗(yàn)證View的狀態(tài);該方法接收一個(gè)ViewAssertion作為參數(shù)嚼松,查看 ViewAssertions提供了哪些方法幫助構(gòu)建ViewAssertion嫡良。
onView(withId(R.id.my_view))            // withId(R.id.my_view) is a ViewMatcher
        .perform(click())               // click() is a ViewAction
        .check(matches(isDisplayed())); // matches(isDisplayed()) is a ViewAssertion

Intents Stub

需要添加espresso-intents依賴庫(kù)。

@Rule //需要聲明使用這個(gè)Rule献酗,繼承于ActivityTestRule寝受,但會(huì)在前后做一些Intents Stub的準(zhǔn)備和清理工作
public IntentsTestRule<DialerActivity> mActivityRule = new IntentsTestRule<>(DialerActivity.class);
//如果有匹配matcher的Intent請(qǐng)求,則用result響應(yīng)
//在啟動(dòng)外部某個(gè)app罕偎,希望得到響應(yīng)時(shí)很有用
intending(Matcher<Intent> matcher).respondWith(ActivityResult result);

//驗(yàn)證當(dāng)前的正在測(cè)試的application發(fā)送了一個(gè)matcher中指定的Intent
//重載的方法允許驗(yàn)證匹配的Intent發(fā)送了多次
intended(Matcher<Intent> matcher)
intended(Matcher<Intent> matcher, times(2));

Test Service

Service的測(cè)試需要用到ServiceTestRule很澄,這個(gè)rule幫助我們start或者成功bind到service,在結(jié)束測(cè)試后還能幫助我們stop或者unbind颜及。這里只給出Test Class的代碼甩苛,完整的代碼在這里

@MediumTest
@RunWith(AndroidJUnit4.class)
public class LocalServiceTest {
    @Rule
    public final ServiceTestRule mServiceRule = new ServiceTestRule();

    @Test
    public void testWithBoundService() throws TimeoutException {
        // Create the service Intent.
        Intent serviceIntent =
                new Intent(InstrumentationRegistry.getTargetContext(), LocalService.class);

        // Data can be passed to the service via the Intent.
        serviceIntent.putExtra(LocalService.SEED_KEY, 42L);

        // Bind the service and grab a reference to the binder.
        IBinder binder = mServiceRule.bindService(serviceIntent);

        // Get the reference to the service, or you can call public methods on the binder directly.
        LocalService service = ((LocalService.LocalBinder) binder).getService();

        // Verify that the service is working correctly.
        assertThat(service.getRandomInt(), is(any(Integer.class)));
    }
}

Test Broadcast

Android沒(méi)有為Broadcast提供類(lèi)似ServiceTestRule這樣的Rule俏站,因?yàn)檫@根本不需要讯蒲。一般如果需要測(cè)試一個(gè)Broadcast,則直接創(chuàng)建這個(gè)這個(gè)receiver的實(shí)例肄扎,然后調(diào)用onReceive()方法墨林,最后驗(yàn)證一些信息。

public class LocalReceiverTest {
    @Test
    public void testOnReceive() throws Exception {
        LocalReceiver localReceiver = new LocalReceiver();
        Intent intent = new Intent();
        intent.putExtra("key", "I Love You!");//onReceive() just saved the key to somewhere
        localReceiver.onReceive(InstrumentationRegistry.getTargetContext(), intent);
        //do some asserts
        assertEquals(getKeyFromSomeWhere(), "I Love You!");
    }  
}

Test ContentProvider

ContentProvider的測(cè)試比較特殊犯祠,我們需要在獨(dú)立的測(cè)試環(huán)境中測(cè)試從而不影響真實(shí)的用戶數(shù)據(jù)萌丈。具體如何測(cè)試,Android官方給了詳細(xì)說(shuō)明雷则。想要查看例子可以看這里

Test File or DataBase

文件或者數(shù)據(jù)庫(kù)的測(cè)試需要注意兩個(gè)測(cè)試之間不能相互影響肪笋,且不能影響到正常的數(shù)據(jù)庫(kù)月劈。這就要求我們自己建立一個(gè)測(cè)試環(huán)境度迂,好在使用RenamingDelegatingContext能夠滿足上面的要求。RenamingDelegatingContext會(huì)將其他操作委托給一個(gè)給定的context對(duì)象猜揪,但在執(zhí)行數(shù)據(jù)庫(kù)/文件相關(guān)的操作時(shí)惭墓,會(huì)用一個(gè)prefix重命名給定的數(shù)據(jù)庫(kù)名或者文件名。所以使用這個(gè)context而姐,我們操作的只是一個(gè)測(cè)試數(shù)據(jù)庫(kù)或者文件腊凶。

public class MyDatabase extends SQLiteOpenHelper {
    private static final String DATABASE_NAME = "database.db";
    private static final int DATABASE_VERSION = 1;

    public MyDatabase(Context context){
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase db){
        // some code
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        // some code
    }
}
public class MyDatabaseTest {
    private MyDatabase db;

    @Before
    public void setUp() throws Exception {
        RenamingDelegatingContext context = new RenamingDelegatingContext(InstrumentationRegistry.getTargetContext(), "test_");
        //每次測(cè)試時(shí),刪除舊的database文件
        context.deleteDatabase("database.db");
        //使用這個(gè)context創(chuàng)建database拴念,文件名對(duì)應(yīng)為'test_database.db'
        db = new MyDatabase(context);
    }

    @After
    public void tearDown() throws Exception {
        db.close(); 
    }

    //@Test
    public void testAddEntry(){
        // Here i have my new database wich is not connected to the standard database of the App
        ...
    }
}

UI Automator Test

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末钧萍,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子政鼠,更是在濱河造成了極大的恐慌风瘦,老刑警劉巖,帶你破解...
    沈念sama閱讀 210,914評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件公般,死亡現(xiàn)場(chǎng)離奇詭異万搔,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)官帘,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,935評(píng)論 2 383
  • 文/潘曉璐 我一進(jìn)店門(mén)瞬雹,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人刽虹,你說(shuō)我怎么就攤上這事酗捌。” “怎么了状婶?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,531評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵意敛,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我膛虫,道長(zhǎng)草姻,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,309評(píng)論 1 282
  • 正文 為了忘掉前任稍刀,我火速辦了婚禮撩独,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘账月。我一直安慰自己综膀,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,381評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布局齿。 她就那樣靜靜地躺著剧劝,像睡著了一般。 火紅的嫁衣襯著肌膚如雪抓歼。 梳的紋絲不亂的頭發(fā)上讥此,一...
    開(kāi)封第一講書(shū)人閱讀 49,730評(píng)論 1 289
  • 那天拢锹,我揣著相機(jī)與錄音,去河邊找鬼萄喳。 笑死卒稳,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的他巨。 我是一名探鬼主播充坑,決...
    沈念sama閱讀 38,882評(píng)論 3 404
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼染突!你這毒婦竟也來(lái)了捻爷?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,643評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤觉痛,失蹤者是張志新(化名)和其女友劉穎役衡,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體薪棒,經(jīng)...
    沈念sama閱讀 44,095評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡手蝎,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,448評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了俐芯。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片棵介。...
    茶點(diǎn)故事閱讀 38,566評(píng)論 1 339
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖吧史,靈堂內(nèi)的尸體忽然破棺而出邮辽,到底是詐尸還是另有隱情,我是刑警寧澤贸营,帶...
    沈念sama閱讀 34,253評(píng)論 4 328
  • 正文 年R本政府宣布吨述,位于F島的核電站,受9級(jí)特大地震影響钞脂,放射性物質(zhì)發(fā)生泄漏揣云。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,829評(píng)論 3 312
  • 文/蒙蒙 一冰啃、第九天 我趴在偏房一處隱蔽的房頂上張望邓夕。 院中可真熱鬧,春花似錦阎毅、人聲如沸焚刚。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,715評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)矿咕。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間痴腌,已是汗流浹背雌团。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,945評(píng)論 1 264
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留士聪,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,248評(píng)論 2 360
  • 正文 我出身青樓猛蔽,卻偏偏與公主長(zhǎng)得像剥悟,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子曼库,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,440評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,732評(píng)論 25 707
  • afinalAfinal是一個(gè)android的ioc区岗,orm框架 https://github.com/yangf...
    passiontim閱讀 15,406評(píng)論 2 45
  • 技術(shù)文檔:官方地址 https://code.google.com/p/android-test-kit/wiki...
    靜jingjing閱讀 1,502評(píng)論 0 3
  • 今天給女兒聽(tīng)寫(xiě)拼音有些進(jìn)步,速度快了毁枯,但個(gè)別音調(diào)表錯(cuò)地方慈缔,罰寫(xiě)10個(gè),以后還要做這方面的練習(xí)种玛。
    李烽熠媽閱讀 164評(píng)論 0 0
  • 想跑步很久了吧?看了很多跑步的文章呀(?? . ??)看了好多減肥成功的文章(?? . ??)之前一直都沒(méi)有開(kāi)始行...
    PImonsterNK閱讀 341評(píng)論 10 3