Java单元测试实践-00.目录(9万多字文档+700多测试示例)
/a82514921/article/details/107969340
1. Gradle单元测试日志、报告与JaCoCo代码覆盖率
1.1. Gradle单元测试日志
参考 /current/userguide/java_testing.html#sec:test_execution ,或 /current/dsl/org.gradle.api.tasks.testing.Test.html#org.gradle.api.tasks.testing.Test:testLogging 。testLogging属性包含一组选项,用于控制记录哪些测试事件以及在记录的级别。还可以通过此属性配置其他日志记录行为。
该属性的类型为TestLoggingContainer,可参考 /current/dsl/org.gradle.api.tasks.testing.logging.TestLoggingContainer.html , 或 /current/javadoc/org/gradle/api/tasks/testing/logging/TestLoggingContainer.html 。
TestLoggingContainer的events属性用于指定需要记录日志的事件类型。events属性定义在TestLoggingContainer的父接口TestLogging中,可参考 /current/javadoc/org/gradle/api/tasks/testing/logging/TestLogging.html#events-java.lang.Object…- 。
events属性可使用TestLogEvent枚举值,可参考 /current/javadoc/org/gradle/api/tasks/testing/logging/TestLogEvent.html 。
TestLogEvent枚举值说明如下:
可将需要记录日志的事件设置为FAILED、PASSED、SKIPPED、STARTED,便于观察测试执行进度。STANDARD_ERROR与STANDARD_OUT会导致输出大量日志,因此不使用。如下所示:
test {testLogging {events "PASSED", "STARTED", "FAILED", "SKIPPED"}}
使用以上配置后,执行测试时,会输出测试类名、方法名,以及事件名称,输出的日志如下所示:
adrninistrator.test.testmock.custom_init_method.TestInitMethodSuppress > test1 PASSEDadrninistrator.test.testmock.custom_init_method.TestInitMethodSuppress > test2 STARTEDadrninistrator.test.testmock.custom_init_method.TestInitMethodSuppress > test2 PASSEDadrninistrator.test.testmock.custom_init_method.TestInitMethodSuppress > test3 STARTED
1.2. 生成测试报告
参考 /current/userguide/java_testing.html#test_reporting 。
Gradle执行test任务时,默认会生成以下结果:
HTML格式的测试报告;XML格式测试结果的格式,与Ant JUnit报告任务兼容,许多其他工具(例如CI服务器)都支持该格式;二进制格式高效的结果,可用于test任务生成其他格式。 reports方法
参考 /current/dsl/org.gradle.api.tasks.testing.Test.html#org.gradle.api.tasks.testing.Test:reports 。
Gradle test任务中包含类型为TestTaskReports的属性reports。
参考TestTaskReports接口的API文档 /current/javadoc/org/gradle/api/tasks/testing/TestTaskReports.html ,其中包含以下方法:
通过以上可知,在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\testdisplayName: Report generated by task ':test' (html)name: htmloutputLocation: Report html property 'outputLocation'outputType: DIRECTORYrequired: Report html property 'required'enabled: truedestination: E:\UnitTest\build\test-results\testdisplayName: Report generated by task ':test' (junitXml)name: junitXmloutputLocation: Report junitXml property 'outputLocation'outputType: DIRECTORYrequired: 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格式测试结果。
打开index.html,可查看各个类的测试结果,测试耗时,标准输出日志,标准错误日志等,如下所示:
XML格式测试报告
HTML格式测试报告生成在“build\test-results\test”目录中,每个类存在一个对应的XML文件,如下所示:
1.3. 使用JaCoCo生成代码覆盖率报告
参考 /current/userguide/jacoco_plugin.html#sec:jacoco_getting_started 。
使用JaCoCo插件可以计算代码覆盖率,添加JaCoCo插件可使用以下方式:
plugins {id 'jacoco'}
1.3.1. jacocoTestReport任务
参考 /current/userguide/jacoco_plugin.html#sec:jacoco_report_configuration 。
使用jacocoTestReport任务可以生成不同格式的代码覆盖率报告。
jacocoTestReport任务对应的类型为JacocoReport,可参考 /current/dsl/org.gradle.testing.jacoco.tasks.JacocoReport.html 、 /current/javadoc/org/gradle/testing/jacoco/tasks/JacocoReport.html 。
jacocoTestReport任务中包含reports()方法,类型为JacocoReportsContainer接口。
参考JacocoReportsContainer接口的API文档 /current/javadoc/org/gradle/testing/jacoco/tasks/JacocoReportsContainer.html ,其中包含以下方法:
通过以上可知,在Gradle jacocoTestReport任务的reports方法中,可以指定csv、html、xml属性的参数。
例如通过以下配置,禁用csv、xml格式的报告,启用html格式报告,并指定报告生成目录:
jacocoTestReport {reports {xml.enabled = falsecsv.enabled = falsehtml.enabled = truehtml.destination = file("${buildDir}/jacocoReport")}}
参考 /current/userguide/jacoco_plugin.html#sec:jacoco_report_violation_rules ,可以检查代码覆盖率是否达到指定值。
1.3.2. 执行测试时生成代码覆盖率报告
在执行测试时,若需要生成代码覆盖率报告,需要同时指定test与jacocoTestReport任务,例如:
gradlew test jacocoTestReportgradlew test -DtestMode=fast jacocoTestReport
test任务相关的参数需要在jacocoTestReport任务之前指定。
测试执行完毕后,经过一段时间代码覆盖率报告会生成。通过上述配置指定生成到“build/jacocoReport”目录时,如下所示:
以被测试代码包名命名的目录中,包含了对应的类的html格式的报告文件。
打开index.html后,可查看各类的代码覆盖率,如下所示:
1.3.2.1. 执行测试失败时生成代码覆盖率报告
参考 /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. 指定生成覆盖率报告的代码类范围
参考 /current/dsl/org.gradle.testing.jacoco.tasks.JacocoReport.html#org.gradle.testing.jacoco.tasks.JacocoReport:classDirectories ,JacocoReport类型中包含属性classDirectories,用于设置需要生成覆盖率报告的代码集,其类型为ConfigurableFileCollection。
参考ConfigurableFileCollection类型的API文档 /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"”。