1.前言
應用測試是每個程序員的基本功,目的是為了保證自己寫的代碼的正確性邮绿。公司一般都有專門的測試人員渠旁,他們負責對整個應用或功能模塊進行測試。兩者之間有什么區(qū)別呢船逮?這得從測試的目的說起顾腊。
測試是為了避免開發(fā)過程中的問題所帶來的風險,本著越早發(fā)現(xiàn)越早解決挖胃,這樣可以減少修改時所需要的代價杂靶。舉個例子,測試人員在應用上線前測出Bug酱鸭,需要在整個應用所有模塊中吗垮,定位到有問題的地方,將錯誤現(xiàn)象告知相應開發(fā)人員去修改凹髓,然后再次合并打包成完整應用烁登。這個過程僅消耗的時間,就比開發(fā)人員完成邏輯后蔚舀,按照文檔進行測試饵沧,再合并打包的時間要長锨络,所以開發(fā)人員懂得測試是很重要的。
2.測試支持庫
Google提供了測試支持庫狼牺,詳細信息參考官網(wǎng)支持庫羡儿。其中AndroidJUnitRunner類是JUnit測試運行器,可在Android設(shè)備上運行JUnit 3或JUnit 4樣式的測試類(不能混合使用)是钥,包括使用Espresso和UI Automator測試框架的設(shè)備掠归。測試運行器可以將測試軟件包和被測試的應用一起加載到設(shè)備、運行測試并報告測試結(jié)果悄泥,如下圖所示:
3.測試的分類
根據(jù)AndroidJUnitRunner的作用可以將測試分為兩大類虏冻,一類運行在計算機本地Java虛擬機(JVM)上,另一類運行在硬件設(shè)備或模擬器上码泞。官方給出的分類是(詳見 Android Studio用戶指南):
- 本地單元測試兄旬。當測試沒有Android框架依賴項或使用Mockito之類的庫模擬Android框架依賴項時,可以利用此類測試來盡量縮短執(zhí)行時間余寥。JUnit測試就是最佳代表领铐,它用于測試功能的正確性,通過斷言進行驗證宋舷。
模塊級build.gradle需要依賴的庫文件:
dependencies {
// Required -- JUnit 4 framework
testCompile 'junit:junit:4.12'
// Optional -- Mockito framework
testCompile 'org.mockito:mockito-core:1.10.19'
}
IDE提供的最簡單的測試:
import org.junit.Test;
import static org.junit.Assert.*;
// 這是測試示例
public class ExampleUnitTest {
// 1.通過注解標明測試方法的生命周期
@Test
public void addition_isCorrect() throws Exception {
// 2.調(diào)用不涉及Android框架的邏輯代碼
int sum = 2 + 2;
// 3.通過斷言判斷對錯
assertEquals(4, sum);
}
}
- 設(shè)備測試绪撵。按有權(quán)訪問的類型,將測試分為兩類祝蝠。
第一類是設(shè)備單元測試音诈,有權(quán)訪問Instrumentation API,可以獲取某些信息(例如绎狭,被測試應用的Context)细溅,并且允許通過測試代碼來控制受測應用。
第二類是自動化UI測試儡嘶,有權(quán)訪問UI組件喇聊,可以編寫集成和功能UI測試來自動化用戶交互,可以解決模擬對象無法滿足的部分Android依賴項蹦狂。
由于自動化UI測試依賴于設(shè)備單元測試誓篱,所以一起說一下基本操作(在模塊級build.gradle中進行)。
首先凯楔,需配置運行器:
android {
defaultConfig {
...
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
}
接著窜骄,需要依賴相應的支持庫:
dependencies {
// Required -- JUnit 4 test runner
androidTestCompile 'com.android.support.test:runner:0.5'
// Optional -- solve a dependency conflict with support-annotations
androidTestCompile 'com.android.support:support-annotations:24.0.0'
// Optional -- JUnit 4 test rules
androidTestCompile 'com.android.support.test:rules:0.5'
// Optional -- Hamcrest library
androidTestCompile 'org.hamcrest:hamcrest-library:1.3'
// Optional -- UI testing with Espresso
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
// solve a dependency conflict with support-annotations
exclude group: 'com.android.support', module: 'support-annotations'
})
// Optional -- UI testing with UI Automator
androidTestCompile 'com.android.support.test.uiautomator:uiautomator-v18:2.1.2'
}
最后,通過設(shè)備單元測試調(diào)用Android框架 API摆屯,進行基本邏輯驗證邻遏;而通過Espresso庫提供的方法訪問視圖,進行交互操作;UI Automator最為強大党远,除了可以與自己應用交互削解,還可以與系統(tǒng)交互富弦,完全模仿用戶操作沟娱,不需要知道應用內(nèi)部實現(xiàn)。詳細使用方式腕柜,請參考官方培訓济似。
4.源集的概念
由于設(shè)備測試內(nèi)置于APK中(與被測試的應用APK分離),因此可能需要擁有自己的AndroidManifest.xml文件來指定最小版本號(除UI Automator需要API 18盏缤,其它為API 8以上即可)和注冊測試專用的運行偵聽器砰蠢。構(gòu)建應用時,Gradle會將多個清單文件合并成一個清單唉铜,先來分析一下里面的邏輯台舱。
開發(fā)過Android的都知道,若新建一個項目潭流,它的工程結(jié)構(gòu)默認只包含app主模塊竞惋。在模塊的src目錄下,每個文件夾都是一個源集(對應構(gòu)建的特定應用版本)灰嫉,存放著代碼和資源拆宛,而共用的部分就放在系統(tǒng)默認的main源集下。
源集的名稱由兩個可缺省的部分組成(src/<productFlavorBuildType>/)讼撒,前半部分為產(chǎn)品風味浑厚,因為每個渠道都有自己的特色,所以基本上以渠道命名根盒;后半部分為構(gòu)建類型钳幅,在上圖中就是androidTest、test炎滞,分別表示設(shè)備測試和本地單元測試敢艰。尤其注意,所有測試均針對debug構(gòu)建類型運行厂榛,若想修改參考如下代碼(位于模塊級build.gradle文件):
android {
...
testBuildType "staging"
}
應用構(gòu)建時需要將特定的源集與main合并盖矫,具體由Gradle配置文件決定。如果不同源集包含同一文件的不同版本击奶,Gradle將按以下優(yōu)先順序決定使用哪一個文件(左側(cè)源集替換右側(cè)源集的文件和設(shè)置):構(gòu)建變體 (含有風味與類型)> 構(gòu)建類型 > 產(chǎn)品風味 > main源集 > 庫依賴項辈双。這樣一來,Gradle便可使用專用的構(gòu)建文件柜砾,同時對與其他應用版本共用的Activity湃望、應用邏輯和資源加以重復利用。
在合并多個清單文件時,Gradle使用同一優(yōu)先順序证芭,使每個構(gòu)建過程都能在最終清單中定義不同的組件或權(quán)限瞳浦。
5.總結(jié)
除了以上測試外,還有其它類型的測試废士,比如壓力測試等叫潦。這篇文章旨在說明測試方法之間的邏輯聯(lián)系、依賴關(guān)系以及適用場景等官硝,具體使用方法會單獨講解矗蕊。若急于入門,可以看看fodroid的文章氢架。