Surefire、Failsafe、Jacoco 与 Maven 插件
Apache Maven Surefire
Apache Maven Surefire 本身是一个测试框架。
Maven Surefire Plugin 和 Maven Failsafe Plugin 都是这个项目的模块。
Surefire 插件
Surefire 是在 maven 的构建生命周期里面,test phase 执行单元测试的插件。
Surefire 的意思是“完全,一定成功的”。任何单元测试失败,都会导致构建失败。
Surefire 跑测试失败,会在现场留下名如hs_err*的文件。
用法
这个插件只有一个 goal,就是 test。
因此,使用它都不需要配置什么 configuration 和 phase。1
2
3
4
5
6
7<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
</plugins>
它默认就会在 test phase 被执行:
1 |
|
不管底层的 test provider 是 JUnit 还是 TestNG,甚至只是一个 pojo,它都可以运行测试。
对于pojo,插件可以自动运行类里面的 public testxxx 方法,也可以使用 JDK 1.4 时代以后使用的断言。
对于 JUnit 之类的 test provider,可以使用以下配置进行并行测试:
1 |
|
类路径太长问题
https://maven.apache.org/surefire/maven-surefire-plugin/examples/class-loading.html
整体而言,就是有些 OS 的命令行不允许太长的类路径。
解决这个问题的思路是,不在命令行内传递类路径,而使用进程内部的参数传递机制。由此诞生的解决方案有:
单独的类加载器。这样可以通过执行一个伪的 booter 程序来绕开类路径的直接限制,在程序内部再 load 我们的目标程序。这个方法也有缺点。首先,
java.class.path
这个系统变量不会包括启动 jar。如果应用程序需要关心这个点,可能会导致问题。其次,程序内部可能会调用Classloader.getSystemClassLoader()而不是使用缺省的类加载器(也就是我们这个 isolated 类加载器)来加载特定的类,这会导致?问题(日后专文讨论)。使用一个 Manifest-Only 的 Jar。这个 Jar 几乎为空,只有一个MANIFEST.MF 文件。JVM 会把这个清单文件里的类路径 honor 起来当做 directive。比如我们可以用一个单独的 Class-Path 的 attribute 来填写我们的很长的类路径。
Failsafe 插件
Failsafe 是在 maven 的构建生命周期里面,test phase 执行集成测试的插件。
Failsafe 看起来是 Surefire 的同义词,但事实上它使用更安全的方式运作。集成测试的失败,和构建过程解耦了,构建不会因此失败。
JaCoCo
JaCoCo 本质上是是一个 java agent,基于 Java 的 Instrumentation API。可以对类文件进行 on-the-fly 的 instrumentation。它是在 class loading 的阶段通过 in memory 字节码增强的形式,进行类型补强。
JaCoCo 本身支持三种数据采集模式:
- 写入文件系统
- 作为一个 server 让其他客户端采集
- 作为一个 client 去连接某个 TCP 端点获取数据
JMX 的接口本身是没有鉴权和授权机制的,所以使用的时候要分清什么是 trusted server。
JaCoCo java agent
JaCoCo 以一个 jar 的形式发布。下载地址,注意它的发布包有 osgi bundle的版本。当做 javaagent 使用,我们应该使用jacocoagent.jar,如果使用它的命令行接口,我们应该使用 jacococli.jar 。它遵循通常的 Java agent 的启动命令语法:
1 |
|
但如果我们使用 JaCoCo Ant tasks 或者 JaCoCo Maven plug-in
javaagent 可用的 options 见这个表格。
JaCoCo Maven plugin
要使用 jacoco 的插件,第一步是获取 maven 的的引用:
1 |
|
这个插件自带的 goal 分别是:
- help
- prepare-agent(最重要的 goal,大部分情况下只使用这个 goal)
- prepare-agent-integration
- merge
- report-aggregate
- check
- dump
- instrument
- restore-instrumented-classes
使用这个插件最起码要配的属性:
1 |
|
然后在使用插件的时候,我们引用了这个 path
1 |
|
上面这个 goal 的主要用处就是准备一个 maven property,用来给其他插件作为 VM argument。详细的含义见这里,在这个例子里,argLine 是一个专门为 surefire 准备的 maven property。
这样下面的 surefire 插件本身就可以把这个生成的 maven property 内插进自己的命令行参数里面:
1 |
|
更详细的配置(包含如何写 report)
https://www.petrikainulainen.net/programming/maven/creating-code-coverage-reports-for-unit-and-integration-tests-with-the-jacoco-maven-plugin/