Android Studio 中的 Jacoco 代码覆盖率
Posted
技术标签:
【中文标题】Android Studio 中的 Jacoco 代码覆盖率【英文标题】:Jacoco code coverage in Android Studio with flavors 【发布时间】:2015-03-21 01:01:28 【问题描述】:一段时间以来,我一直在尝试安静地运行 Jacoco 测试覆盖。我已经尝试了这些主题中报告的几种可能的解决方案:
android test code coverage with JaCoCo Gradle plugin
How do I get a jacoco coverage report using Android gradle plugin 0.10.0 or higher?
我正在使用 genymotion 在模拟设备中运行测试。 这是我添加到 build.gradle 的内容:
apply plugin: 'jacoco'
android
jacoco
version "0.7.1.201405082137"
buildTypes
debug
testCoverageEnabled = true
jacoco
toolVersion "0.7.1.201405082137"
要运行它,我使用类似的东西
./gradlew clean
./gradlew createFLAVOR_NAMEDebugCoverageReport
相关生成的文件/文件夹是:
/build/intermediates/coverage-instrumented-classes
/build/intermediates/jacoco
/build/outputs/code-coverage/connected/flavors/MyFlavor/coverage.ec
但是,@build/reports/jacoco/test/html/index.html 或任何 html 页面/代码覆盖率报告 @/build/outputs 都没有。
我还尝试创建一个专门的任务来构建覆盖率报告:
def coverageSourceDirs = [
'src/main/java',
]
task jacocoTestReport(type: JacocoReport, dependsOn: "connectedAndroidTestFLAVOR_NAMEDebug")
group = "Reporting"
description = "Generate Jacoco coverage reports after running tests."
reports
xml.enabled = true
html.enabled = true
classDirectories = fileTree(
dir: './build/intermediates/classes/debug',
excludes: ['**/R*.class',
'**/*$InjectAdapter.class',
'**/*$ModuleAdapter.class',
'**/*$ViewInjector*.class'
])
sourceDirectories = files(coverageSourceDirs)
executionData = files("$buildDir/jacoco/connectedAndroidTestMyFlavorDebug.exec")
// Bit hacky but fixes https://code.google.com/p/android/issues/detail?id=69174.
// We iterate through the compiled .class tree and rename $$ to $.
doFirst
new File("$buildDir/intermediates/classes/").eachFileRecurse file ->
if (file.name.contains('$$'))
file.renameTo(file.path.replace('$$', '$'))
然后是 ./gradlew clean 和 ./gradlew jacocoTestReport。输出与上面相同,因此没有包含覆盖率报告或任何其他覆盖率文件的 html 页面。
我目前正在使用最新 gradle 版本的 Android Studio v1.0.2。 我对 gradle 很陌生,所以我可能在这里遗漏了一些基本的东西。
谢谢
【问题讨论】:
github.com/bumptech/glide/blob/master/library/build.gradle 使用您的工具进行采样。 How to get code coverage using Android Studio? 的可能副本 【参考方案1】:花了一整天的时间追查这个问题后,我发现了问题所在。与我看到的示例相反,testDebug 构建生成的文件不是 .exec 文件@$buildDir/jacoco/testDebug.exec。
使用我的 gradle 和 studio 版本,生成的文件是 .ec @build/outputs/code-coverage/connected/flavors/myFlavor/coverage.ec
我没有找到任何与此相关的信息。然而,这可能是最近的变化,通过创建自定义 JacocoReport 任务并相应地更改 executionData 变量,我已经解决了这个问题。 这是我的实现:
task jacocoTestReport(type: JacocoReport)
def coverageSourceDirs = [
'src/main/java'
]
group = "Reporting"
description = "Generates Jacoco coverage reports"
reports
xml
enabled = true
destination "$buildDir/reports/jacoco/jacoco.xml"
csv.enabled false
html
enabled true
destination "$buildDir/jacocoHtml"
classDirectories = fileTree(
dir: 'build/intermediates/classes',
excludes: ['**/R.class',
'**/R$*.class',
'**/BuildConfig.*',
'**/Manifest*.*',
'**/*Activity*.*',
'**/*Fragment*.*'
]
)
sourceDirectories = files(coverageSourceDirs)
additionalSourceDirs = files(coverageSourceDirs)
executionData = files('build/outputs/code-coverage/connected/flavors/smartcompanion/coverage.ec')
【讨论】:
通过所有这些提示,尽管我通过测试活动运行,但测试报告中的代码覆盖率仍然为 0%。但我的报告位于$buildDir/reports/coverage/debug
,而不是$buildDir/reports/jacoco/jacoco.xml
或$buildDir/jacocoHtml
。我已经花了很多时间在我的 Instrumentation Tests 中集成 Jacoco 代码覆盖率,并且在帖子中使用了很多描述。但它仍然不能正确运行。奇怪的是我的coverage.ec
文件是空的。
这个 sn-p 是否应该排除所有片段和活动?那里可能有需要测试的代码。
@unlimited101 您使用哪种设备?如果使用三星可能会出现问题。尝试使用 HTC、摩托罗拉或其他一个【参考方案2】:
使用带有 Android 风格的 Jacoco 测试覆盖率报告:
假设您有名为“免费”和“付费”的口味
在 build.gradle 所在的项目模块目录(默认应用程序)中创建文件 jacoco.gradle,它应该在 build.gradle 文件旁边。目录结构如下图
>app > jacoco.gradle
将下面的代码粘贴到我们在步骤 1 中创建的文件中,该代码具有自我解释的 cmets 以便理解
apply plugin: 'jacoco'
jacoco
toolVersion = "0.7.5.201505241946"
project.afterEvaluate
// Grab all build types and product flavors
def buildTypes = android.buildTypes.collect type ->
type.name
def productFlavors = android.productFlavors.collect flavor ->
flavor.name
// When no product flavors defined, use empty
if (!productFlavors) productFlavors.add('')
//iterate over the flavors
productFlavors.each
productFlavorName ->
//iterate over build types like debug,release,prod etc.
buildTypes.each
buildTypeName ->
//sourceName — e.g. freeDebug ,sourcePath — e.g. free/debug
def sourceName, sourcePath
if (!productFlavorName)
sourceName = sourcePath = "$buildTypeName"
else
sourceName = "$productFlavorName$buildTypeName.capitalize()"
sourcePath = "$productFlavorName/$buildTypeName"
// testTaskName — e.g. testFreeDebugtest task that the coverage task depends on,
def testTaskName = "test$sourceName.capitalize()UnitTest"
// Create coverage task of form 'testFlavorTypeCoverage' depending on 'testFlavorTypeUnitTest'
task "$testTaskNameCoverage" (type:JacocoReport, dependsOn: "$testTaskName")
group = "Reporting"
description = "Generate Jacoco coverage reports on the $sourceName.capitalize() build."
classDirectories = fileTree(
dir: "$project.buildDir/intermediates/classes/$sourcePath",
excludes: [
'**/R.class',
'**/R$*.class',
'**/*$ViewInjector*.*',
'**/*$ViewBinder*.*',
'**/BuildConfig.*',
'**/Manifest*.*'
]
)
def coverageSourceDirs = [
"src/main/java",
"src/$productFlavorName/java",
"src/$buildTypeName/java"
]
additionalSourceDirs = files(coverageSourceDirs)
sourceDirectories = files(coverageSourceDirs)
executionData = files("$project.buildDir/jacoco/$testTaskName.exec")
reports
//enables and disable the type of file you need
xml.enabled = false
html.enabled = true
在 android studio 终端中运行以下命令来构建应用程序
./gradlew clean assemble
在构建成功后,运行以下命令以生成测试报告(将字符串 testFreeDebugUnitTestCoverage
更改为您的特定风格/构建类型,例如付费版本命令将是 ./gradlew testPaidDebugUnitTestCoverage
)
./gradlew testFreeDebugUnitTestCoverage
终端应该会提示成功,现在进入目录
>app > build > reports >jacoco >$testName >look for html or xml file report file
现在您可以在浏览器中打开并查看 html 测试覆盖率文件
【讨论】:
197NODMB25385:app tarun$ ./gradlew testFreeDebugUnitTestCoverage bash: ./gradlew: No such file or directory @JJD以上是关于Android Studio 中的 Jacoco 代码覆盖率的主要内容,如果未能解决你的问题,请参考以下文章
安卓代码覆盖率:android studio+ gradle+jacoco
如何从android项目中的jacoco测试覆盖率报告中排除方法
从精准化测试看ASM在Android中的强势插入-JaCoco初探
从精准化测试看ASM在Android中的强势插入-JaCoco初探