官方文檔鏈接:https://developer.android.google.cn/training/testing/integration-testing/index.html
1.前言
如果應用程序使用用戶不直接交互的組件磷脯,例如Service或ContentProvider,則需要驗證這些組件行為是正確的碘菜。當開發(fā)這些組件時犬缨,應該養(yǎng)成寫集成測試的習慣扮匠,以便驗證應用程序的組件運行于設備或模擬器上的行為吠架。
注意:安卓并沒有為BroadcastReceiver提供獨立的測試用例類,若需驗證它響應正確精居,可以給它發(fā)送Intent對象來測試锄禽。或者靴姿,可以通過調用
InstrumentationRegistry.getTargetContext()
方法創(chuàng)建BroadcastReceiver實例沃但,然后調用它需測試的方法(通常,就是onReceive()
方法)佛吓。
下面將介紹如何使用安卓平臺提供的測試APIs和工具宵晚,來構建自動化集成測試。
2.測試Service
如果正在實現(xiàn)一個本地Service作為應用程序的組件维雇,應該測試Service來確保不會出現(xiàn)意料之外的行為淤刃。可以創(chuàng)建設備單元測試來驗證吱型,Service中的行為是正確的逸贾;例如,Service存儲和返回有效數據值津滞,且正確地執(zhí)行數據操作铝侵。
安卓測試支持庫為獨立測試Service對象提供API。ServiceTestRule類是JUnit 4規(guī)則触徐,可以在單元測試方法運行前啟動Service咪鲜,并在測試完成后關閉Service。通過使用此測試規(guī)則锌介,確保測試方法運行前嗜诀,與Service的連接已經建立了猾警。要了解更多關于JUnit 4規(guī)則,請參閱JUnit文檔隆敢。
注意:ServiceTestRule類不支持IntentService對象的測試发皿。如果需要測試IntentService對象,可以通過將邏輯封裝到獨立的類中拂蝎,并創(chuàng)建相應的單元測試來代替穴墅。
2.1.設置測試環(huán)境
為Service構建集成測試之前,請確保項目已配置設備測試温自。
2.2.創(chuàng)建Service集成測試
集成測試應該寫成JUnit 4測試類玄货。要了解更多關于創(chuàng)建JUnit 4測試類和使用JUnit 4斷言方法,請參閱創(chuàng)建設備單元測試類悼泌。為Service創(chuàng)建集成測試松捉,在測試類定義之前添加 @RunWith(AndroidJUnit4.class)
注解,還需要指定安卓測試支持庫提供的AndroidJUnitRunner類作為默認測試運行器馆里。在運行設備單元測試中有更詳細的描述隘世。
接著測試中,通過使用@Rule
注解鸠踪,創(chuàng)建ServiceTestRule實例丙者。
@Rule
public final ServiceTestRule mServiceRule = new ServiceTestRule();
下面的示例展示,如何實現(xiàn)一個關于Service的集成測試营密。testWithBoundService()
測試方法驗證應用程序成功綁定本地Service械媒,且Service接口行為正常。
@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)));
}
2.3.運行Service集成測試
可以從Android Studio或命令行運行集成測試评汰,確認項目已指定AndroidJUnitRunner作為默認設備運行器纷捞。
3.測試ContentProvider
如果正在實現(xiàn)ContentProvider,來存儲和檢索數據或允許其它應用程序訪問數據键俱,應該測試它以確保不會出現(xiàn)意料之外的行為兰绣。下面描述如何測試公共的ContentProvider,也適用于私有的(僅提供給自己的應用程序)编振。
3.1.創(chuàng)建ContentProvider集成測試
在安卓中,應用程序將ContentProvider視為提供數據表的數據APIs臭埋,從而隱藏內部實現(xiàn)踪央。ContentProvider可能有許多公共常量,但它通常即使有公共方法也很少瓢阴,而且沒有公共變量畅蹂。為此,應該僅基于ContentProvider(被設計成在它和它的用戶之間提供契約)的公共成員編寫測試荣恐。
ContentProvider允許訪問實際用戶數據液斜,所以確保在獨立的測試環(huán)境下測試它是很重要的累贤。這種方式可以只運行測試用例中顯式設置的數據依賴,還意味著測試不會修改實際用戶數據少漆。例如臼膏,應該避免編寫失敗的測試,因為數據會遺留下來示损。類似的渗磅,測試應該避免通過ContentProvider添加或刪除實際相關信息。借助ProviderTestCase2類獨立測試ContentProvider检访,可以使用安卓模擬對象類(如IsolatedContext和MockContentResolver)來訪問文件和數據庫信息始鱼,而不影響實際用戶數據。
集成測試應該寫成JUnit 4測試類脆贵。要了解更多關于創(chuàng)建JUnit 4測試類和使用JUnit 4斷言医清,請參閱創(chuàng)建本地單元測試類。為ContentProvider創(chuàng)建集成測試卖氨,必須執(zhí)行下面的開發(fā)步驟:
創(chuàng)建測試類作為ProviderTestCase2的子類状勤。
在測試類定義之前添加
@RunWith(AndroidJUnit4.class)
注解。指定安卓測試支持庫提供的AndroidJUnitRunner類作為默認測試運行器双泪。
-
根據InstrumentationRegistry類設置Context對象持搜,請參閱下面的代碼片段示例。
@Override protected void setUp() throws Exception { super.setUp(); setContext(InstrumentationRegistry.getTargetContext()); }
3.2.ProviderTestCase2如何工作
用于測試ContentProvider的是ProviderTestCase2的子類焙矛,作為基類的它繼承自AndroidTestCase葫盼,所以提供了JUnit測試框架和測試應用權限的安卓特定方法。這個類最重要的功能是它的初始化村斟,能創(chuàng)建獨立的測試環(huán)境贫导。
初始化在ProviderTestCase2的構造函數中完成,它的子類在調用自己的構造函數時也會執(zhí)行蟆盹。ProviderTestCase2的構造函數會創(chuàng)建一個IsolatedContext對象孩灯,用于執(zhí)行文件和數據庫操作,但不引出其它與安卓系統(tǒng)的交互逾滥。因為操作發(fā)生在設備或模擬器的本地目錄下峰档,并有特定的前綴。接著寨昙,構造函數會為測試創(chuàng)建MockContentResolver來使用讥巡。最后,構造函數在測試時創(chuàng)建ContentProvider實例舔哪。這是普通的ContentProvider對象欢顷,但它是從IsolatedContext獲取所需的環(huán)境信息,所以被限制在獨立的測試環(huán)境下工作捉蚤,測試用例類中的所有測試都是針對這個獨立的對象運行的抬驴。
為ContentProvider運行集成測試的方式與設備單元測試相同炼七,按照運行設備單元測試中描述的步驟。
3.3.測試的內容
下面是一些測試ContentProvider的具體指南布持。
- 用ContentResolver的方法測試:即使可以在ProviderTestCase2中實例化一個ContentProvider對象豌拙,也總該通過ContentResolver對象使用相應的URI來測試。這樣做確保鳖链,通過執(zhí)行與常規(guī)應用程序將使用的相同交互來測試ContentProvider姆蘸。
- 公共的ContentProvider作為契約測試:如果想讓ContentProvider對其它應用程序公開和有效,應該將它作為契約測試芙委。下面給出如何做的一些例子:
- 測試ContentProvider公開暴露的常量:例如逞敷,查詢指向ContentProvider某數據表中列名的常量,它們應該總是由ContentProvider公開定義的灌侣。
- 測試ContentProvider提供的所有URIs:ContentProvider可能提供幾種URIs推捐,每種涉及數據的不同方面。
- 測試無效的URIs:單元測試應該有意使用無效URI調用ContentProvider侧啼,并查找錯誤牛柒。一個好的ContentProvider設計時,對于無效的URIs會拋出IllegalArgumentException異常痊乾。
- 標準的ContentProvider交互測試:大多數ContentProvider提供六種可訪問方法皮壁,如
query()
、insert()
哪审、delete()
蛾魄、update()
、getType()
和onCreate()
湿滓。測試應該驗證上述所有方法是否有效滴须,更詳細的描述參考Content Providers。 - 業(yè)務邏輯測試:如果內容提供者實現(xiàn)業(yè)務邏輯叽奥,應該測試它扔水。業(yè)務邏輯包括處理無效值,數據或算術計算朝氓,消除或合并重復魔市。
4.總結
本文主要講了如何測試用戶看不見、摸不到的系統(tǒng)組件膀篮,包括Service和ContentProvider嘹狞。系統(tǒng)組件是開發(fā)工作中經常用到的,可由于它們與系統(tǒng)息息相關誓竿,不太容易排除其它因素的影響,所以一定要注意使用提供的類創(chuàng)建獨立環(huán)境下的對象谈截。