Maven与测试
Maven 的主要职责之一就是自动运行单元测试,通过 maven-surefire-plugin 与主
流的单元测试框架 Junit3、Junit4、TestNG 集成,并能够自动生成丰富的结果报告。
1. maven-surefire-plugin 简介
Maven 本身并不是一个单元测试框架,Maven 只是在构建执行到特定生命周期阶
段的时候,通过插件来执行 Junit 或者 TestNG 的测试用例,这个插件称之为测试运行
器(Test Runner),也就是 maven-surefire-plugin。
a) 阶段绑定
生命周期阶段,需要绑定到某个插件的目标才能完成真正的工作,test 阶段正是与
maven-surefire-plugin 的 test 目标绑定了,这是一个内置绑定。
b) 测试指令
mvn test
c) 测试源码路径
默认 src/test/java。
d) 测试类的命名模式(Junit 为例)
i. **/Test*.java
任何子目录下所有命名以 Test 开头的 Java 类。
ii. **/*Test.java
任何子目录下所有命名以 Test 结尾的 Java 类。
iii. **/*TestCase.java
任何子目录下所有命名以 TestCase 结尾的 Java 类。
iv. 例外
以 Tests 结尾的测试类不会得以自动执行。
2. 跳过测试
在日常开发总会遇到跳过测试这种情况,不管是由于有信心没有错误,还是由于测
试时间过于耗时,都不推荐这样做,更好的做法是优化测试。
a) 跳过测试(不推荐)
i. 命令行
加入参数 skipTests 就可以了,例如:
mvn package –DskipTests
ii. pom.xml
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>2.5</version> <configuration> <skipTests>true</skipTests> </configuration> </plugin>
b) 临时跳过测试(不推荐)
i. 命令行
mvn package –Dmaven.test.skip = true
1) maven.test.skip
这个参数控制了maven-compiler-plugin和maven-surefire-plugin 两
个插件的行为,测试代码编译跳过了,测试运行也跳过了。
ii. pom.xml
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>2.1</version> <configuration> <skip>true</skip> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>2.5</version> <configuration> <skip>true</skip> </configuration> </plugin>
c) 注意事项
maven-compiler-plugin的testCompile目标和maven-surefire-plugin的
test 目标都提供了一个参数 skip 用来跳过测试编译和测试运行,而这个参数对应的
命令行表达式为 maven.test.skip。
3. 动态指定运行测试用例
如果仅仅为了一个失败的测试用例而反复运行所有测试,未免太浪费时间了,当项
目中测试的数目比较大的时候,这种浪费尤其明显。
a) test 参数
maven-surefire-plugin 提供了一个 test 参数让 Maven 用户能够在命令行指定要
运行的测试用例。
i. 测试用例类名
mvn test –Dtest = RandomGeneratorTest
只有 RandomGeneratorTest 这一个测试类得到运行。
ii. 星号匹配符
mvn test –Dtest = Random*Test
匹配多个测试类,只要满足以 Random 开头,以 Test 结尾。
iii. 逗号指定多个测试用例
mvn test –Dtest = RandomGeneratorTest,AccountCaptchaTest
匹配这两个测试类,多个之间用逗号隔开。
iv. 结合使用星号和逗号
mvn test –Dtest = Random*Test, AccountCaptchaTest
v. 找不到匹配类
mvn test –Dtest
这样的命令会导致构建失败,但是可以告诉 maven-surefire-plugin 即使没有任何测试也不要报错。
mvn test –Dtest –DfailIfNoTests = false
实际上这是另外一种跳过测试的方法。
4. 包含与排除测试用例
maven-surefire-plugin 还是允许用户通过额外的配置来自定义包含一些其他测
试类,或者排除一些符合默认命名模式的测试类。
a) 包含
由于历史原因,有些项目所有测试类的名称都是以 Tests 结尾,这样的名字不符合默
认的 3 种模式,因此不会被自动运行,但可以这样配置。
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>2.5</version> <configuration> <includes> <include>**/*Tests.java</include> </includes> </configuration> </plugin>
i. **
前面的 2 个*用来匹配任意路径。
ii. *
匹配任意字符。
b) 排除
类似可以使用 excludes 元素排除一些符合默认命名模式的测试类。
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>2.5</version> <configuration> <excludes> <exclude>**/*ServiceTest.java</exclude> <exclude>**/DaoTest.java</exclude> </excludes> </configuration> </plugin>
i. 排除以 ServiceTest 结尾的测试类
ii. 排除 DaoTest 的测试类
iii. 有了 excludes 配置后,maven-surefire-plugin 将不再自动运行他们
虽然他们都符合命名模式**/*Test.java。
5. 测试报告
除了命令行输出,Maven 用户可以使用 maven-surefire-plugin 等插件以文件的
形式生成更丰富的测试报告。
a) 测试术语(基于 Junit)
i. Failures
失败,表示要测试的结果与期望值不一致。
ii. Errors
错误,表示测试代码活产品代码发生了未预期的错误。
iii. Skipped
表示那些被标记为忽略的测试方法。
b) 基本的测试报告
一般情况下,maven-surefire-plugin 会在项目的 target/surefire-reports 目录
下生成两种格式的错误报告。
i. 简单文本格式
例如:org.lichee.core.AppTest.txt
ii. 与 Junit 兼容的 XML 格式
XML 格式的测试报告主要是为了支持工具的解析,如 eclipse 的 Junit 插件可以直接打开这样的报告。
例如:TEST-org.lichee.core.AppTest.xml
1) 报告标准
由于这种 XML 格式已经成为了 Java 单元测试报告的事实标准,一些其他
工具也能使用他们。如:持续继承服务器 Hudson 就能使用这样的文件提
供持续继承的测试报告。
c) 测试覆盖率报告
测试覆盖率是衡量项目代码质量的一个重要的参考指标,Cobertura 是一个优
秀的开源测试覆盖率统计工具,Maven 通过 cobertura-maven-plugin 与之集成,
就可以使用简单的命令为 Maven 项目生成测试覆盖率报告。
i. pom.xml
<plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>cobertura-maven-plugin</artifactId> <version>2.6</version> </plugin>
ii. 指令
mvn cobertura:cobertura
iii. 查看报告
打开 target/site/cobertura 下的 index.html 文件。
1) 全部类的测试覆盖报告
2) 具体某个类的测试覆盖报告
6. 重用测试代码
默认的打包行为是不会包含测试代码的,因此在使用外部依赖的时候,其构件一般
都不会包含测试代码。但这个需求又是很常见的,可能存在高质量的测试基类、或者是
一些常见的测试工具类。
a) maven-jar-plugin
这个插件可以将测试类打包。
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <executions> <execution> <goals> <goal>test-jar</goal> </goals> </execution> </executions> </plugin>
i. jar 目标
生成构件的 jar 包,绑定在 default 生命周期的 package 阶段。
例如:lichee-core-1.0.0.jar。
ii. test-jar 目标
生成构件的测试 jar 包,默认绑定声明周期阶段为 package。
例如:lichee-core-1.0.0-tests.jar。
1) 引用
所有的测试包构件都使用特殊的 test-jar 打包类型。
<dependency> <groupId>org.lichee</groupId> <artifactId>lichee-core</artifactId> <version>1.0.0</version> <type>test-jar</type> <scope>test</scope> </dependency>