構(gòu)建一個(gè)測(cè)試程序已經(jīng)被集成到應(yīng)用項(xiàng)目中,沒(méi)有必要再專門建立一個(gè)測(cè)試項(xiàng)目。
單元測(cè)試的支持被試驗(yàn)性地添加到 1.1 版本中,請(qǐng)看 這頁(yè)。本章節(jié)剩余部分描述了可以在真機(jī)(或模擬器)上運(yùn)行的 “instrumentation tests”,以及需要構(gòu)建的獨(dú)立、測(cè)試性的 APK。
正如前面所提到的,緊鄰main
_sourceSet_的就是androidTest
sourceSet,默認(rèn)路徑在src/androidTest/下。
在這個(gè)測(cè)試_sourceSet_中會(huì)構(gòu)建一個(gè)使用Android測(cè)試框架,并且可以部署到設(shè)備上的測(cè)試apk來(lái)測(cè)試應(yīng)用程序。這里面包含單元測(cè)試,集成測(cè)試,和后續(xù)UI自動(dòng)化測(cè)試。
這個(gè)測(cè)試sourceSet不應(yīng)該包含AndroidManifest.xml文件,因?yàn)檫@個(gè)文件會(huì)自動(dòng)生成。
下面這些值可能會(huì)在測(cè)試應(yīng)用配置中使用到:
testPackageName
testInstrumentationRunner
testHandleProfiling
testfunctionalTest
正如前面所看到的,這些配置在defaultConfig對(duì)象中配置:
android {
defaultConfig {
testPackageName "com.test.foo"
testInstrumentationRunner "android.test.InstrumentationTestRunner"
testHandleProfiling true
testFunctionalTest true
}
}
在測(cè)試應(yīng)用程序的manifest文件中,instrumentation節(jié)點(diǎn)的targetPackage屬性值會(huì)自動(dòng)使用測(cè)試應(yīng)用的package名稱設(shè)置,即使這個(gè)名稱是通過(guò)defaultConfig
或者_(dá)Build Type_對(duì)象自定義的。這也是manifest文件需要自動(dòng)生成的一個(gè)原因。
另外,這個(gè)測(cè)試_sourceSet_也可以擁有自己的依賴。 默認(rèn)情況下,應(yīng)用程序和他的依賴會(huì)自動(dòng)添加的測(cè)試應(yīng)用的classpath中,但是也可以通過(guò)以下來(lái)擴(kuò)展:
dependencies {
androidTestCompile 'com.google.guava:guava:11.0.2'
}
測(cè)試應(yīng)用通過(guò)assembleTest
task來(lái)構(gòu)建。assembleTest
不依賴于main中的assemble
task,需要手動(dòng)設(shè)置運(yùn)行,不能自動(dòng)運(yùn)行。
目前只有一個(gè)_Build Type_被測(cè)試。默認(rèn)情況下是debug
Build Type,但是這也可以通過(guò)以下自定義配置:
android {
...
testBuildType "staging"
}
正如前面提到的,標(biāo)志性task connectedCheck
要求一個(gè)連接的設(shè)備來(lái)啟動(dòng)。
這個(gè)過(guò)程依賴于androidTest
task,因此將會(huì)運(yùn)行androidTest
。這個(gè)task將會(huì)執(zhí)行下面內(nèi)容:
assembleDebug
和assembleTest
)。如果有多于一個(gè)連接設(shè)備,那么所有測(cè)試都會(huì)同時(shí)運(yùn)行在所有連接設(shè)備上。如果其中一個(gè)測(cè)試失敗,不管是哪一個(gè)設(shè)備算失敗。
所有測(cè)試結(jié)果都被保存為XML文檔,路徑為:
_build/androidTest-results_
(這類似于JUnit的運(yùn)行結(jié)果保存在build/test-results)
同樣,這也可以自定義配置:
android {
...
testOptions {
resultsDir = "$project.buildDir/foo/results"
}
}
這里的android.testOptions.resultsDir
將由Project.file(String)
獲得。
測(cè)試Android庫(kù)項(xiàng)目的方法與應(yīng)用項(xiàng)目的方法類似。
唯一的不同在于整個(gè)庫(kù)(包括它的依賴)都是自動(dòng)作為依賴庫(kù)被添加到測(cè)試應(yīng)用中。結(jié)果就是測(cè)試APK不單只包含它的代碼,還包含了庫(kù)項(xiàng)目自己和庫(kù)的所有依賴。 庫(kù)的manifest被組合到測(cè)試應(yīng)用的manifest中(作為一些項(xiàng)目引用這個(gè)庫(kù)的殼)。
androidTest
task的變改只是安裝(或者卸載)測(cè)試APK(因?yàn)闆](méi)有其它APK被安裝)。
其它的部分都是類似的。
當(dāng)運(yùn)行單元測(cè)試的時(shí)候,Gradle會(huì)輸出一份HTML格式的報(bào)告以方便查看結(jié)果。 Android plugin也是基于此,并且擴(kuò)展了HTML報(bào)告文件,它將所有連接設(shè)備的報(bào)告都合并到一個(gè)文件里面。
一個(gè)項(xiàng)目將會(huì)自動(dòng)生成測(cè)試運(yùn)行。默認(rèn)位置為:build/reports/androidTests
這非常類似于JUnit的報(bào)告所在位置build/reports/tests,其它的報(bào)告通常位于build/reports/< plugin >/。
這個(gè)路徑也可以通過(guò)以下方式自定義:
android {
...
testOptions {
reportDir = "$project.buildDir/foo/report"
}
}
報(bào)告將會(huì)合并運(yùn)行在不同設(shè)備上的測(cè)試結(jié)果。
在一個(gè)配置了多個(gè)應(yīng)用或者多個(gè)庫(kù)項(xiàng)目的多項(xiàng)目里,當(dāng)同時(shí)運(yùn)行所有測(cè)試的時(shí)候,生成一個(gè)報(bào)告文件記錄所有的測(cè)試可能是非常有用的。
為了實(shí)現(xiàn)這個(gè)目的,需要使用同一個(gè)依賴文件(譯注:指的是使用android gradle插件的依賴文件)中的另一個(gè)插件??梢酝ㄟ^(guò)以下方式添加:
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:0.5.6'
}
}
apply plugin: 'android-reporting'
這必須添加到項(xiàng)目的根目錄下,例如與settings.gradle文件同個(gè)目錄的build.gradle文件中。
之后,在命令行中導(dǎo)航到項(xiàng)目根目錄下,輸入以下命令就可以運(yùn)行所有測(cè)試并合并所有報(bào)告:
gradle deviceCheck mergeAndroidReports --continue
注意:
這里的--continue選項(xiàng)將允許所有測(cè)試,即使子項(xiàng)目中的任何一個(gè)運(yùn)行失敗都不會(huì)停止。如果沒(méi)有這個(gè)選項(xiàng),第一個(gè)失敗測(cè)試將會(huì)終止全部測(cè)試的運(yùn)行,這可能導(dǎo)致一些項(xiàng)目沒(méi)有執(zhí)行過(guò)它們的測(cè)試。
Lint支持,譯者注:Lint是一個(gè)可以檢查Android項(xiàng)目中存在的問(wèn)題的工具
從0.7.0版本開(kāi)始,你可以為項(xiàng)目中一個(gè)特定的Variant(變種)版本運(yùn)行l(wèi)int,也可以為所有Variant版本都運(yùn)行l(wèi)int。它將會(huì)生成一個(gè)報(bào)告描述哪一個(gè)Variant版本中存在著問(wèn)題。
你可以通過(guò)以下lint選項(xiàng)配置lint。通常情況下你只需要配置其中一部分,以下列出了所有可使用的選項(xiàng):
android {
lintOptions {
// set to true to turn off analysis progress reporting by lint
quiet true
// if true, stop the gradle build if errors are found
abortOnError false
// if true, only report errors
ignoreWarnings true
// if true, emit full/absolute paths to files with errors (true by default)
//absolutePaths true
// if true, check all issues, including those that are off by default
checkAllWarnings true
// if true, treat all warnings as errors
warningsAsErrors true
// turn off checking the given issue id's
disable 'TypographyFractions','TypographyQuotes'
// turn on the given issue id's
enable 'RtlHardcoded','RtlCompat', 'RtlEnabled'
// check *only* the given issue id's
check 'NewApi', 'InlinedApi'
// if true, don't include source code lines in the error output
noLines true
// if true, show all locations for an error, do not truncate lists, etc.
showAll true
// Fallback lint configuration (default severities, etc.)
lintConfig file("default-lint.xml")
// if true, generate a text report of issues (false by default)
textReport true
// location to write the output; can be a file or 'stdout'
textOutput 'stdout'
// if true, generate an XML report for use by for example Jenkins
xmlReport false
// file to write report to (if not specified, defaults to lint-results.xml)
xmlOutput file("lint-report.xml")
// if true, generate an HTML report (with issue explanations, sourcecode, etc)
htmlReport true
// optional path to report (default will be lint-results.html in the builddir)
htmlOutput file("lint-report.html")
// set to true to have all release builds run lint on issues with severity=fatal
// and abort the build (controlled by abortOnError above) if fatal issues are found
checkReleaseBuilds true
// Set the severity of the given issues to fatal (which means they will be
// checked during release builds (even if the lint target is not included)
fatal 'NewApi', 'InlineApi'
// Set the severity of the given issues to error
error 'Wakelock', 'TextViewEdits'
// Set the severity of the given issues to warning
warning 'ResourceAsColor'
// Set the severity of the given issues to ignore (same as disabling the check)
ignore 'TypographyQuotes'
}
}