生成Android单元测试代码覆盖率报告的两种方式

前言

本篇文章主要介绍在写完单元测试后,如何测试代码的覆盖率,从而更好的查缺补漏。下面我会介绍两种查看覆盖率的方法;一种是借助Jacoco,通过Gradle生成html报告。另一种是使用Android Studio自带的Coverage,在运行后展示在Coverage列表中,再根据需求导出即可。

目录

  • 配置信息
  • 使用Jacoco查看代码覆盖率
  • 使用AS自带Coverage查看代码覆盖率
  • 参考

配置信息

在测试前先说一下,现在用的各种包的版本和AS版本

  • Android Studio 3.5.2
  • SDK 28
  • Gradle 3.4.2
  • Java JRE 1.8.0
  • Jacoco 0.8.5

因为版本的不同,在配置上或界面上的展示效果也不尽相同,接下来我们进入正题,开始代码覆盖率的查看。

使用Jacoco查看代码覆盖率

添加Jacoco.gradle文件

Jacoco.gradle文件默认不会自动生成需要自己手动添加,添加的位置和你要测试Moudle或者Lib包中的build.gradle文件在同一层级:

放置位置

创建好文件后,在文件中添加内容,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
apply plugin: 'jacoco'

jacoco {
toolVersion = "0.8.5" //指定jacoco的版本
reportsDir = file("$buildDir/JacocoReport") //指定jacoco生成报告的文件夹
}

tasks.withType(Test) {
jacoco.includeNoLocationClasses = true
}

android {
buildTypes {
debug {
//打开覆盖率统计开关
testCoverageEnabled = true
}
}
}

//依赖于testDebugUnitTest任务
task jacocoTestReport(type: JacocoReport, dependsOn: 'testDebugUnitTest') {
group = "reporting" //指定task的分组
reports {
xml.enabled = true //开启xml报告
html.enabled = true //开启html报告
}

def debugTree = fileTree(dir: "${buildDir}/intermediates/javac/debug/compileDebugJavaWithJavac/classes/你的包名", //指定类文件夹 包名以 / 分割
includes: ["**/*.*"], //包含类的规则,这里我们生成所有类的测试报告
excludes: ['**/R.class',
'**/R$*.class',
'**/BuildConfig.*',
'**/Manifest*.*']) //排除类的规则

def mainSrc = "${project.projectDir}/src/main/java" //指定源码目录

sourceDirectories = files([mainSrc])
classDirectories = files([debugTree])
executionData = files("${buildDir}/jacoco/testDebugUnitTest.exec") //指定报告数据的路径
}

上面的jacoco.gradle文件中的内容都有注释说明,重点说一下def debugTree选项

def debugTree

这里指定的类文件夹,在../classes/你的包名后面写的就是你的包名,比如你的包名叫:

com.app.unit.test

那么在指定类文件夹这一项就这样写:

def debugTree

在配置里面说过当前使用的gradle3.4.2,在gradle3.x之后class文件的目录是上面的:

/intermediates/javac/debug/compileDebugJavaWithJavac/classes/

如果你的gradle版本在3.x之前class文件目录需要替换成为:

/intermediates/classes/debug

两者对比写法:

3.x前后对比

再有就是下面includesexcludes标签,前者是代表要测试哪些类,后者代表忽略哪些类,两者都可以指定多个文件,目前我没有找到忽略某个文件夹的方法,如果谁知道,可以跟我说一下。

使用Jacoco进行测试

jacoco.gradle文件配置好以后,我们需要项目的buidle.gradle中引用,这里的buidle.gradle就是和jacoco.gradle同一层级的文件,引用方式如下:

apply from: 'jacoco.gradle'

把上面代码加入到buidle.gradle文件中,放置在最外层(第一行或第二行)。

引用jacoco

接着同步一下项目,我们就可以开始运行查看了。

运行jacoco

点击AS右侧的gradle工具栏

右侧gradle工具栏

如果你在你的AS右侧没有看到gradle的标签,可以从AS上方的菜单栏进入:

View -- Tool Windows -- Gradle

view方式进入

打开gradle后,找到其中的两个命令testDebugUintTestjacocoTestReport

两个命令

首先双击运行testDebugUintTest命令,之后在AS底部Run标签中可以看到,项目中所有的用例在运行,有错误会在列表中展示,最后测试多少用例,成功多少,失败多少,都会显示出来,我们可以根据提示进行修改,直到没有错误:

Run错误

上图是双击后测试的结果,我们可以看到哪些测试用例出现了错误,而且给出错误提示。

Run正确

上图是经过改正后,所有的测试用例都通过了(有一个忽略的方法),这时我们的用例就跑完了。

接着我们双击运行jacocoTestReport命令,同样会在Run中展示,等运行完成,我们的报告也就生成了。

查看报告

刚才我们双击的testDebugUintTest命令,会生成单元测试的报告,而双击的jacocoTestReport命令会生成测试覆盖率报告,文件放置的位置在你测试的MoudleLib下的build文件夹下,报告在reportsJacocoReports中:

报告路径

用浏览器分别打开index.xml文件可以看到详细的报告。

测试报告:

测试报告

覆盖率报告:

覆盖率报告

点击每项可以查看具体的测试情况,绿色代表已经测试部分,红色代表未测试到的部分,黄色代表部分执行,就像if else中的部分代码被执行。

覆盖率报告

至此关于Jacoco覆盖率的相关介绍就结束了。

使用AS自带Coverage查看代码覆盖率

除了jacoco三方库可以测试代码覆盖率外,AS自身也带有一种测试代码覆盖率的工具,下面我们就来介绍一下。

我们在运行测试类的时候,有两种方式;一种是在测试类中点击类名所在行的左侧,选择Run xx.class

运行测试类1

或者是点击选中此类,右键,然后Run xx.class

运行测试类2

上图可以看到箭头所指的就是我们运行测试类时,选择的方式。我们再看图中被圈住的命令

Run xx.class With Coverage

这一个命令,就是我们要说的另一种生成覆盖率报告的方式。

我们选择一个类,运行Run xx.class With Coverage命令,然后会出现下面的弹框:

添加弹框

我们选择中间的按钮Add to active suites,就会看到我们测试的类,添加到了Coverage工具栏的列表中,如下图所示:

覆盖率列表

我们看一下这个列表,在列表第一行可以看到ElementClassMethodLine等选项(红框圈住的位置),它们分别代表的是测试的类所在路径/包此路径下类测试占比方法数测试占比代码测试的覆盖率我们都可以看到,其中的Line就是我们需要的代码覆盖率。

可能你在点击按钮Add to active suites时,在Coverage工具栏的工具栏中并没有出现列表中的内容,而是显示一句话:

no coverage results. click Edit to fix configuration settings

解决方法是:我们点击界面上的Edit按钮,此时会跳转到Edit configurations界面,我们选择Junit测试选项,选中测试的类,在右侧选择code coverage标签,把下方的Enable coverage in test folders勾选上,别忘了最后点击apply按钮,操作步骤如下:

coverage不显示的情况

选中之后,再重复上述操作,就可以在列表中看到覆盖率等内容了。

上面只说了看了一个测试文件的方式,如果想要看二个或者多个测试类的覆盖率的怎么做呢,只需要继续运行其他想看的类,选择Add to active suites按钮,测试的文件就添加到列表中了。

如果想要测试整个项目的代码覆盖率情况,我们可以点击test目录下java文件下项目包名,点击右键,选择Run xx With Coverage,具体操作如下:

整个项目测试

等测试用例运行完之后,接下来的操作和前面介绍的测试一个类的方式一样,只是这时候展示在列表中的文件有点多:

完整目录列表

我们从文件中顺着包名的顺序找到我们的测试文件,可以点进去看代码的覆盖率实际上这时我们可以在左侧的Project目录中看到,每个文件夹下的代码的测试覆盖率情况。

project看覆盖率

点进测类的代码,在左侧也可以看到被测试到每一行代码都会有绿色的线条标注。

代码标记

注意:如果所有的类一起测试生成覆盖率报告,如果其中的某一个类没有测试通过,那么测试结果显示出的覆盖率为0%,遇到这种情况,我们只需将错误的位置修改后,单独运行,添加到列表中即可。

覆盖率为0

如果觉得这种查看的方式不爽,我们还可以生成像jacoco那样的html文件,方式也很简单。还是打开我们右侧的Coverage工具栏,在左侧我们看到有一排小的按钮,我们选择最下方的按钮:

生成报告按钮

在弹出的提示框中选择报告生成后放置的位置:

选择报告生成位置

选好后点击save按钮,会将列表中所有的测试用例运行的覆盖率结果导出。之后我们在之前指定的文件下找到生成的报告,用浏览器打开index.html文件,就可以看我们的覆盖率情况了,里面有很多不是我们的代码,我们只需找到我们包名下的文件查看即可。

html报告

其中覆盖率为0%的是测试用例运行失败的情况

到这里两种查看测试用例的方式都介绍完了,个人建议在测试整个项目的测试率是使时用jacoco,在查看某一个类的时候,使用AS自带工具。

参考

本篇文章中的jacoco部分的内容是参考CSDN博主唯鹿单元测试分类的第八篇文章

Android单元测试(八):Dagger与单元测试

其中的项目截图也是其GitHub项目的demo截取的。

强烈建议对单元测试感兴趣的小伙伴,通篇阅读唯鹿的单元测试系列文章,写的通俗易懂,深入浅出。

-------------The End-------------