Gradle for Android(六) 運行測試

為了確保app或者library的質(zhì)量,自動化測試非常重要屁桑。很長一段時間,ADT缺少對自動化測試的支持栏赴,但是最近蘑斧,Google花費了很大的努力幫助開發(fā)者進行測試。一些老的框架進行了升級须眷,并添加了一些新的框架竖瘾,以確保我們可以徹底測試app和library。我們不僅可以在Android Studio中運行它們柒爸,也可以使用Gradle在命令行運行准浴。

本章,我們會探索測試Android app和library的幾種方式捎稚。我們還將研究Gradle如何幫助實現(xiàn)自動化測試乐横。

本章包含如下內(nèi)容:

  • 單元測試
  • 功能測試
  • 測試覆蓋率

單元測試

好的單元測試不僅能保證工程質(zhì)量,也可以用來檢測新的代碼是否會破壞原有功能今野。Android Studio和Gradle Android插件對單元測試提供了本地支持葡公,你只需要進行少量配置就可以使用。

JUnit

JUnit是一個非常流行的單元測試庫条霜,已經(jīng)有了十多年的歷史催什。它使測試變得簡單易懂。需要記住的是宰睡,這些流行的單元測試僅對測試業(yè)務(wù)邏輯有用蒲凶,不能測試Android SDK相關(guān)的代碼。

在寫測試之前拆内,你需要創(chuàng)建一個目錄旋圆。按照慣例,目錄名稱為test麸恍,和main目錄在同一級別灵巧。目錄結(jié)構(gòu)如下:

app
└─── src
     ├─── main
     │     ├─── java
     │     │    └─── com.example.app
     │     └───res
     └─── test
           └─── java
                └───com.example.app

隨后你可以在src/test/java/com.example.app目錄添加測試類。

為了使用JUnit的最新特性抹沪,建議使用JUnit4.0以上版本刻肄。添加如下依賴:

dependencies {
    testCompile 'junit:junit:4.12'
}

注意我們此處使用testCompile,而不是compile融欧,這可以確保只在運行測試時構(gòu)建此依賴敏弃,正式打包時不會。

如果你的某個構(gòu)建類型或者product flavors有一些特性噪馏,你也可以為這個特定的構(gòu)建單獨添加測試依賴权她。比如虹茶,你只想為付費版添加JUnit測試,可以這樣做:

dependencies {
    testPaidCompile 'junit:junit:4.12'
}

配置好這些隅要,就可以編寫測試代碼了。下面的例子用來測試一個類中兩數(shù)相加的方法:

import org.junit.Test;
import static org.junit.Assert.assertEquals;

public class LogicTest {
    @Test
    public void addingNegativeNumberShouldSubtract() {
    Logic logic = new Logic();
    assertEquals("6 + -2 must be 4", 4, logic.add(6, -2));
    assertEquals("2 + -5 must be -3", -3, logic.add(2, -5));
    }
}

要運行所有級別的測試董济,只需執(zhí)行gradlew測試步清。如果你只想在某個構(gòu)建變體運行測試,只需要添加上這個變體的名字虏肾。比如廓啊,執(zhí)行gradlewtestDebug將只在debug變體上運行測試。如果測試失敗封豪,Gradle會在命令行中打印錯誤信息谴轮。如果運行成功,Gradle會顯示BUILD SUCCESSFUL吹埠。

單行測試失敗將導(dǎo)致真?zhèn)€測試任務(wù)失敗第步。這意味著并不是所有的測試都會執(zhí)行。如果你希望這個測試單元在所有的構(gòu)建變體上都被執(zhí)行缘琅,添加continue標(biāo)識:

$ gradlew test --continue

你也可以僅為某個構(gòu)建變體編寫測試粘都,只需要將測試類放在相應(yīng)的目錄就可以了。比如刷袍,想要測試付費版本的話翩隧,可以將測試類放在src/testPaid/java/com.example.app中。

如果你不想運行整個測試單元呻纹,只想測試某個類堆生,可以添加標(biāo)識:

$ gradlew testDebug --tests="*.LogicTest"

執(zhí)行測試不僅會運行所有的測試,還會生成一個測試報告雷酪,路徑為app/build/reports/tests/debug/index.html淑仆。測試報告可以幫助排查問題,在自動測試中非常有用太闺。Gradle會為每個構(gòu)建變體生成一個測試報告糯景。

你也可以在Android Studio中運行測試。在IDE中可以得到及時反饋省骂,并且可以點擊失敗的測試蟀淮,從而快速定位到問題代碼。

如果你想測試包含Android特有類或者資源引用的代碼钞澳,常規(guī)單元測試是行不通的怠惶,這會引發(fā)java.lang.RuntimeException: Stub!錯誤。為了解決這個問題轧粟,你可以自己實現(xiàn)Android SDK的每個方法策治,或者使用一個模擬框架脓魏。幸運的是,一些庫解決了這個問題通惫,其中最流行的是Robolectric茂翔,它提供了簡單的方式來測試Android功能,并且不需要設(shè)備或者模擬器履腋。

Robolectric

使用Robolectric珊燎,你可以編寫使用了Android SDK和資源的測試,并在JVM中運行它遵湖。也就是說悔政,你不需要設(shè)備或者模擬器就可以測試UI組件。

為了使用Robolectric延旧,你需要添加一些依賴谋国。除了Robolectric,你也需要JUnit迁沫。如果你使用了Android support library芦瘾,你還需要Robolectric shadow。

apply plugin: 'org.robolectric'

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:22.2.0'

    testCompile 'junit:junit:4.12'
    testCompile'org.robolectric:robolectric:3.0'
    testCompile'org.robolectric:shadows-support:3.0'
}

和常規(guī)單元測試一樣弯洗,Robolectric測試類需要放在src/test/java/com.example.app目錄下旅急。不同的是,你可以在測試中使用Android類和資源牡整。比如藐吮,測試驗證一個TextView的文本在點擊按鈕后發(fā)生了變化:

@RunWith(RobolectricTestRunner.class)
@Config(manifest = "app/src/main/AndroidManifest.xml", sdk = 18)
public class MainActivityTest {
    @Test
    public void clickingButtonShouldChangeText() {
        AppCompatActivity activity = Robolectric.buildActivity(MainActivity.class).create().get();
        Button button = (Button)activity.findViewById(R.id.button);
        TextView textView = (TextView)activity.findViewById(R.id.label);
        button.performClick();
        assertThat(textView.getText().toString(), equalTo(activity.getString(R.string.hello_robolectric)));
    }
}

Robolectric在Android L系統(tǒng)和suport library上存在一些問題。如果你碰到無法找到資源和兼容庫相關(guān)的錯誤逃贝,可以嘗試在模塊中添加一個project.properties文件谣辞,文件包含如下內(nèi)容:

android.library.reference.1=../../build/intermediates/exploded-aar/com.android.support/appcompat-v7/22.2.0
android.library.reference.2=../../build/intermediates/exploded-aar/com.android.support/support-v4/22.2.0

這會幫助Robolectric找到兼容庫資源。

功能測試

功能測試用于測試應(yīng)用的幾個模塊是否如預(yù)期那樣正常工作沐扳。比如泥从,你可以創(chuàng)建一個功能測試,用于確認點擊一個按鈕是否會打開一個新的頁面沪摄。Android有幾個功能測試框架躯嫉,最簡單易用的是Espresso。

Espresso

Google創(chuàng)建了Espresso杨拐,使開發(fā)者更容易編寫功能測試祈餐。它在Android support repository中提供,你可以使用SDK Manager安裝哄陶。

為了在設(shè)備上運行測試帆阳,你需要有一個測試運行器。在testing support library中屋吨,Google提供了AndroidJUnitRunner測試運行器蜒谤,它可以幫助你在Android設(shè)備上運行JUnit測試類山宾。測試運行器會在設(shè)備上安裝應(yīng)用APK和測試APK,運行所有測試鳍徽,然后根據(jù)結(jié)果創(chuàng)建測試報告资锰。

假如你已經(jīng)下載了testing support library,可以如下配置測試運行器:

defaultConfig {
    testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}

在使用Espresso之前阶祭,你還需要配置幾個依賴:

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:22.2.0'

    androidTestCompile 'com.android.support.test:runner:0.3'
    androidTestCompile 'com.android.support.test:rules:0.3'
    androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2'
    androidTestCompile 'com.android.support.test.espresso:espresso-contrib:2.2'
}

你需要引用testing support library和espresso-core才能使用Espresso台妆。最后一個依賴,espresso-contrib胖翰,是Espresso的一些補充特性,但不是核心庫的一部分切厘。

注意這些依賴使用的是androidTestCompile配置萨咳,而不是testCompile。這是為了區(qū)分單元測試和功能測試疫稿。

如果這個時候嘗試運行測試培他,你會得到下面的錯誤:

Error: duplicate files during packaging of APK app-androidTest.apk
    Path in archive: LICENSE.txt
    Origin 1: ...\hamcrest-library-1.1.jar
    Origin 2: ...\junit-dep-4.10.jar

錯誤的描述很清晰,因為一個重復(fù)的文件遗座,Gradle將不能完成構(gòu)建舀凛。幸運的是,它僅是一個許可描述途蒋,所以我們可以在構(gòu)建中移除猛遍。這個錯誤本身也包含如何修復(fù)的信息:

You can ignore those files in your build.gradle:

android {
    packagingOptions {
        exclude 'LICENSE.txt'
    }
}

配置好構(gòu)建文件之后,你就可以添加測試了号坡。功能測試和常規(guī)的單元測試放在不同的目錄下懊烤。正如依賴配置一樣,你需要使用androidTest代替test宽堆,正確的功能測試目錄是src/androidTest/java/com.example.app腌紧。下面是一個測試類的例子,用于檢測MainActivityTextView中的文本是否正確畜隶。

@RunWith(AndroidJUnit4.class)
@SmallTest
public class TestingEspressoMainActivityTest {
    @Rule
    public ActivityTestRule<MainActivity> mActivityRule = new ActivityTestRule<>(MainActivity.class);

    @Test
    public void testHelloWorldIsShown() {
        onView(withText("Hello world!")).check(matches(isDisplayed()));
    }
}

在運行Espresso測試之前壁肋,你需要確保有一個設(shè)備或者模擬器。如果你忘記連接設(shè)備籽慢,運行測試任務(wù)會引發(fā)如下異常:

Execution failed for task ':app:connectedAndroidTest'.
>com.android.builder.testing.api.DeviceException:
java.lang.RuntimeException: No connected devices!

當(dāng)你連接上設(shè)備或者啟動了模擬器之后浸遗,你可以使用gradlew connectedCheck來運行Espresso測試。這個任務(wù)會執(zhí)行connectedAndroidTestcreateDebugCoverageReport嗡综,前者會在所有連接的設(shè)備上為debug變體運行所有測試乙帮,后者會生成一個測試報告。

你可以在應(yīng)用的build/outputs/reports/androidTests/connected目錄找到生成的測試報告极景。

功能測試報告會顯示運行測試的設(shè)備以及Android版本察净。你可以同時在多個設(shè)備上運行測試驾茴,所以設(shè)備信息可以很容易的查看特定設(shè)備或者特定版本的問題。

如果你想在Android Studio中得到測試的反饋氢卡,你需要設(shè)置run/debug配置锈至。run/debug配置代表一組run/debug啟動屬性。Android Studio的工具欄有一個配置選擇器译秦,你可以選擇想要使用的run/debug配置峡捡。

圖1 Android Studio run/debug配置選擇器

你可以點擊Edit Configurations…打開配置編輯器,創(chuàng)建一個新的Android測試配置筑悴。選擇測試模塊们拙,設(shè)備運行器設(shè)置為AndroidJUnitRunner

圖2 編輯配置窗口

將新配置保存后阁吝,你就可以在配置選擇器中選擇它砚婆,然后點擊Run按鈕來運行所有測試。

在Android Studio中運行Espresso測試有一個問題:不會生成測試報告突勇。這是因為Android Studio執(zhí)行connectedAndroidTest任務(wù)装盯,而不是connectedCheck任務(wù),而測試報告是由connectedCheck生成的甲馋。

測試覆蓋率

為Android工程編寫測試后埂奈,需要知道測試在代碼庫中的覆蓋率。Java有很多測試覆蓋率工具定躏,最流行的是Jacoco账磺,它也是默認支持的,很容易上手共屈。

Jacoco

啟用覆蓋率報告非常簡單绑谣。你只需要在測試的構(gòu)建類型中設(shè)置testCoverageEnabled = true

buildTypes {
    debug {
        testCoverageEnabled = true
    }
}

啟用測試覆蓋率后拗引,執(zhí)行gradlew connectedCheck會生成覆蓋率報告借宵。真正生成報告的是createDebugCoverageReport。即使它沒有被列入文檔矾削,執(zhí)行gradlew tasks時也不會出現(xiàn)在任務(wù)列表中壤玫,但你可以直接運行它。而由于createCoverageReport依賴connectedCheck哼凯,所以你不可以單獨運行它們欲间。依賴connectedCheck也表明你需要連接設(shè)備或者模擬器來生成測試覆蓋率報告。

執(zhí)行任務(wù)之后断部,你可以在app/build/outputs/reports/coverage/debug/index.html路徑找到覆蓋率報告猎贴。每個構(gòu)建變體有各自的目錄。

如果你想設(shè)置一個特定版本的Jacoco,只需:

jacoco {
    toolVersion = "0.7.1.201405082137"
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末她渴,一起剝皮案震驚了整個濱河市达址,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌趁耗,老刑警劉巖沉唠,帶你破解...
    沈念sama閱讀 217,406評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異苛败,居然都是意外死亡满葛,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評論 3 393
  • 文/潘曉璐 我一進店門罢屈,熙熙樓的掌柜王于貴愁眉苦臉地迎上來嘀韧,“玉大人,你說我怎么就攤上這事缠捌∪槎辏” “怎么了?”我有些...
    開封第一講書人閱讀 163,711評論 0 353
  • 文/不壞的土叔 我叫張陵鄙币,是天一觀的道長。 經(jīng)常有香客問我蹂随,道長十嘿,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,380評論 1 293
  • 正文 為了忘掉前任岳锁,我火速辦了婚禮绩衷,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘激率。我一直安慰自己咳燕,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,432評論 6 392
  • 文/花漫 我一把揭開白布乒躺。 她就那樣靜靜地躺著招盲,像睡著了一般。 火紅的嫁衣襯著肌膚如雪嘉冒。 梳的紋絲不亂的頭發(fā)上曹货,一...
    開封第一講書人閱讀 51,301評論 1 301
  • 那天,我揣著相機與錄音讳推,去河邊找鬼顶籽。 笑死,一個胖子當(dāng)著我的面吹牛银觅,可吹牛的內(nèi)容都是我干的礼饱。 我是一名探鬼主播,決...
    沈念sama閱讀 40,145評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼镊绪!你這毒婦竟也來了匀伏?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,008評論 0 276
  • 序言:老撾萬榮一對情侶失蹤镰吆,失蹤者是張志新(化名)和其女友劉穎帘撰,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體万皿,經(jīng)...
    沈念sama閱讀 45,443評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡摧找,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,649評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了牢硅。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蹬耘。...
    茶點故事閱讀 39,795評論 1 347
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖减余,靈堂內(nèi)的尸體忽然破棺而出综苔,到底是詐尸還是另有隱情,我是刑警寧澤位岔,帶...
    沈念sama閱讀 35,501評論 5 345
  • 正文 年R本政府宣布如筛,位于F島的核電站,受9級特大地震影響抒抬,放射性物質(zhì)發(fā)生泄漏杨刨。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,119評論 3 328
  • 文/蒙蒙 一擦剑、第九天 我趴在偏房一處隱蔽的房頂上張望妖胀。 院中可真熱鬧,春花似錦惠勒、人聲如沸赚抡。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,731評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽涂臣。三九已至,卻和暖如春售担,著一層夾襖步出監(jiān)牢的瞬間肉康,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,865評論 1 269
  • 我被黑心中介騙來泰國打工灼舍, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留吼和,地道東北人。 一個月前我還...
    沈念sama閱讀 47,899評論 2 370
  • 正文 我出身青樓骑素,卻偏偏與公主長得像炫乓,于是被迫代替她去往敵國和親刚夺。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,724評論 2 354

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

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,108評論 25 707
  • afinalAfinal是一個android的ioc末捣,orm框架 https://github.com/yangf...
    passiontim閱讀 15,429評論 2 45
  • 我今天一邊煮面侠姑,一邊配料,一邊在回想舅舅昨晚說的《一分鐘》箩做,悟到自己在工作時莽红,如能把自己所有的靈魂協(xié)調(diào)到最佳狀態(tài),...
    臣服于道的村民閱讀 389評論 0 0
  • 月亮雙魚的妹子找我咨詢感情問題邦邦,她的故事是安吁,伴侶是一個理性的人,一開始相愛時她很欣賞對方能在她被情感淹沒的時候幫助...
    封子末閱讀 4,534評論 0 3
  • 無聊的時候 抄寫著“從此山水不相逢” 洗澡的時候 單曲循環(huán)馬老五的《Don't wanna know》 可是夜深的...
    黎暖蘇閱讀 182評論 0 0