Java单元测试实践-23.Gradle单元测试日志、报告与JaCoCo代码覆盖率

Java单元测试实践-00.目录(9万多字文档+700多测试示例)
https://blog.csdn.net/a82514921/article/details/107969340

1. Gradle单元测试日志、报告与JaCoCo代码覆盖率

1.1. Gradle单元测试日志

参考 https://docs.gradle.org/current/userguide/java_testing.html#sec:test_execution ,或 https://docs.gradle.org/current/dsl/org.gradle.api.tasks.testing.Test.html#org.gradle.api.tasks.testing.Test:testLogging 。testLogging属性包含一组选项,用于控制记录哪些测试事件以及在记录的级别。还可以通过此属性配置其他日志记录行为。

该属性的类型为TestLoggingContainer,可参考 https://docs.gradle.org/current/dsl/org.gradle.api.tasks.testing.logging.TestLoggingContainer.html , 或 https://docs.gradle.org/current/javadoc/org/gradle/api/tasks/testing/logging/TestLoggingContainer.html 。

TestLoggingContainer的events属性用于指定需要记录日志的事件类型。events属性定义在TestLoggingContainer的父接口TestLogging中,可参考 https://docs.gradle.org/current/javadoc/org/gradle/api/tasks/testing/logging/TestLogging.html#events-java.lang.Object…- 。

events属性可使用TestLogEvent枚举值,可参考 https://docs.gradle.org/current/javadoc/org/gradle/api/tasks/testing/logging/TestLogEvent.html 。

TestLogEvent枚举值说明如下:

枚举常量描述
FAILED某个测试已失败
PASSED某个测试已成功完成
SKIPPED某个测试已跳过
STANDARD_ERROR某个测试在标准错误写入的信息
STANDARD_OUT某个测试在标准输出写入的信息
STARTED某个测试已开始

可将需要记录日志的事件设置为FAILED、PASSED、SKIPPED、STARTED,便于观察测试执行进度。STANDARD_ERROR与STANDARD_OUT会导致输出大量日志,因此不使用。如下所示:

test {
    testLogging {
        events "PASSED", "STARTED", "FAILED", "SKIPPED"
    }
}

使用以上配置后,执行测试时,会输出测试类名、方法名,以及事件名称,输出的日志如下所示:

adrninistrator.test.testmock.custom_init_method.TestInitMethodSuppress > test1 PASSED

adrninistrator.test.testmock.custom_init_method.TestInitMethodSuppress > test2 STARTED

adrninistrator.test.testmock.custom_init_method.TestInitMethodSuppress > test2 PASSED

adrninistrator.test.testmock.custom_init_method.TestInitMethodSuppress > test3 STARTED

1.2. 生成测试报告

参考 https://docs.gradle.org/current/userguide/java_testing.html#test_reporting 。

Gradle执行test任务时,默认会生成以下结果:

  1. HTML格式的测试报告;
  2. XML格式测试结果的格式,与Ant JUnit报告任务兼容,许多其他工具(例如CI服务器)都支持该格式;
  3. 二进制格式高效的结果,可用于test任务生成其他格式。
  • reports方法

参考 https://docs.gradle.org/current/dsl/org.gradle.api.tasks.testing.Test.html#org.gradle.api.tasks.testing.Test:reports 。

Gradle test任务中包含类型为TestTaskReports的属性reports。

参考TestTaskReports接口的API文档 https://docs.gradle.org/current/javadoc/org/gradle/api/tasks/testing/TestTaskReports.html ,其中包含以下方法:

返回类型方法名称说明
DirectoryReportgetHtml()指示测试执行结果的HTML报告
JUnitXmlReportgetJunitXml()JUnit XML格式的测试结果

通过以上可知,在Gradle test任务的reports方法中,可以指定html、junitXml属性的参数。

在Gradle test任务中使用以下代码查看reports方法的html、junitXml属性参数值:

test {
    reports {
        html {
            println "destination: " + getDestination()
            println "displayName: " + getDisplayName()
            println "name: " + getName()
            println "outputLocation: " + getOutputLocation()
            println "outputType: " + getOutputType()
            println "required: " + getRequired()
            println "enabled: " + isEnabled()
        }
        junitXml {
            println "destination: " + getDestination()
            println "displayName: " + getDisplayName()
            println "name: " + getName()
            println "outputLocation: " + getOutputLocation()
            println "outputType: " + getOutputType()
            println "required: " + getRequired()
            println "enabled: " + isEnabled()
        }
    }
}

执行结果如下所示:

destination: E:\UnitTest\build\reports\tests\test
displayName: Report generated by task ':test' (html)
name: html
outputLocation: Report html property 'outputLocation'
outputType: DIRECTORY
required: Report html property 'required'
enabled: true

destination: E:\UnitTest\build\test-results\test
displayName: Report generated by task ':test' (junitXml)
name: junitXml
outputLocation: Report junitXml property 'outputLocation'
outputType: DIRECTORY
required: Report junitXml property 'required'
enabled: true

可以看到HTML格式的测试报告生成目录为“build\reports\tests\test”,默认开启;XML格式的测试报告生成目录为“build\test-results\test”,默认开启。

使用setEnabled()、setDestination()方法设置报告生成是否开启、生成目录时执行失败,例如“setEnabled(true)”“setDestination(file("$buildDir/reports"))”,提示不允许修改,如“The value for Report html property ‘required’ is final and cannot be changed any further.”“The value for Report html property ‘outputLocation’ is final and cannot be changed any further.”。在Gradle 4.1版本中支持修改以上参数。

  • HTML格式测试报告

HTML格式测试报告生成在“build\reports\tests\test”目录中,classes目录中保存了各个类的HTML格式测试结果,packages目录中保存了各个包的HTML格式测试结果。

pic

打开index.html,可查看各个类的测试结果,测试耗时,标准输出日志,标准错误日志等,如下所示:

pic

pic

  • XML格式测试报告

HTML格式测试报告生成在“build\test-results\test”目录中,每个类存在一个对应的XML文件,如下所示:

pic

1.3. 使用JaCoCo生成代码覆盖率报告

参考 https://docs.gradle.org/current/userguide/jacoco_plugin.html#sec:jacoco_getting_started 。

使用JaCoCo插件可以计算代码覆盖率,添加JaCoCo插件可使用以下方式:

plugins {
    id 'jacoco'
}

1.3.1. jacocoTestReport任务

参考 https://docs.gradle.org/current/userguide/jacoco_plugin.html#sec:jacoco_report_configuration 。

使用jacocoTestReport任务可以生成不同格式的代码覆盖率报告。

jacocoTestReport任务对应的类型为JacocoReport,可参考 https://docs.gradle.org/current/dsl/org.gradle.testing.jacoco.tasks.JacocoReport.html 、 https://docs.gradle.org/current/javadoc/org/gradle/testing/jacoco/tasks/JacocoReport.html 。

jacocoTestReport任务中包含reports()方法,类型为JacocoReportsContainer接口。

参考JacocoReportsContainer接口的API文档 https://docs.gradle.org/current/javadoc/org/gradle/testing/jacoco/tasks/JacocoReportsContainer.html ,其中包含以下方法:

返回类型方法名称说明
SingleFileReportgetCsv()JaCoCo的CSV格式报告
DirectoryReportgetHtml()JaCoCo的HTML格式报告
SingleFileReportgetXml()JaCoCo的XML格式报告

通过以上可知,在Gradle jacocoTestReport任务的reports方法中,可以指定csv、html、xml属性的参数。

例如通过以下配置,禁用csv、xml格式的报告,启用html格式报告,并指定报告生成目录:

jacocoTestReport {
    reports {
        xml.enabled = false
        csv.enabled = false
        html.enabled = true
        html.destination = file("${buildDir}/jacocoReport")
    }
}

参考 https://docs.gradle.org/current/userguide/jacoco_plugin.html#sec:jacoco_report_violation_rules ,可以检查代码覆盖率是否达到指定值。

1.3.2. 执行测试时生成代码覆盖率报告

在执行测试时,若需要生成代码覆盖率报告,需要同时指定test与jacocoTestReport任务,例如:

gradlew test jacocoTestReport
gradlew test -DtestMode=fast jacocoTestReport

test任务相关的参数需要在jacocoTestReport任务之前指定。

测试执行完毕后,经过一段时间代码覆盖率报告会生成。通过上述配置指定生成到“build/jacocoReport”目录时,如下所示:

pic

以被测试代码包名命名的目录中,包含了对应的类的html格式的报告文件。

打开index.html后,可查看各类的代码覆盖率,如下所示:

pic

pic

pic

1.3.2.1. 执行测试失败时生成代码覆盖率报告

参考 https://docs.gradle.org/current/userguide/command_line_interface.html#sec:continue_build_on_failure 。

默认情况下,Gradle会在任何任务失败后中止执行并立即使构建失败。

当使用–continue选项执行时,Gradle不会在遇到第一个失败时立即停止,而是会执行依赖任务已成功完成的所有任务。每个遇到的失败都将在构建结束时报告。如果任务失败,则将不执行任何依赖于该任务的后续任务。

默认情况下,执行test与jacocoTestReport任务,若test任务失败,则jacocoTestReport任务不会执行。

为了使test任务执行出现失败时,jacocoTestReport任务也能执行,需要使用–continue选项,如下所示:

gradlew test jacocoTestReport --continue

1.3.3. 指定生成覆盖率报告的代码类范围

参考 https://docs.gradle.org/current/dsl/org.gradle.testing.jacoco.tasks.JacocoReport.html#org.gradle.testing.jacoco.tasks.JacocoReport:classDirectories ,JacocoReport类型中包含属性classDirectories,用于设置需要生成覆盖率报告的代码集,其类型为ConfigurableFileCollection。

参考ConfigurableFileCollection类型的API文档 https://docs.gradle.org/current/javadoc/org/gradle/api/file/ConfigurableFileCollection.html ,可通过setFrom()方法设置源代码路径。

可通过以下方式指定生成覆盖率报告的代码类范围,可参考示例项目unittest.gradle文件test任务(使用Groovy配置文件中的配置参数):

jacocoTestReport {
    classDirectories.setFrom(files(classDirectories.files.collect {
        fileTree('dir': it,
                'include': ['com/adrninistrator/service/**', 'com/adrninistrator/applicationlistener/**'],
                'exclude': ['**/TestPrivateNonVoidService1**'])
    }))
}

可通过fileTree的include/exclude属性指定需要包含/排除的生成覆盖率报告的代码。

在Gradle 4.x版本(如4.1、4.7)中,需要使用以下方式指定生成覆盖率报告的代码类范围:

jacocoTestReport {
    afterEvaluate {
        classDirectories = files(classDirectories.files.collect {
            fileTree('dir': it,
                'include': ['com/adrninistrator/service/**', 'com/adrninistrator/applicationlistener/**'],
                'exclude': ['**/TestPrivateNonVoidService1**'])
        })
    }
}

1.3.4. 覆盖率报告显示代码中文乱码问题

在Windows环境执行Gradle命令进行单元测试并生成代码覆盖率报告时,若不指定JVM的编码参数,生成的代码覆盖率报告中显示的代码中文会乱码,需要修改gradlew.bat脚本,在DEFAULT_JVM_OPTS参数中指定“"-Dfile.encoding=UTF-8"”。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值