maven-surefire-plugin
Posted 西魏陶渊明
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了maven-surefire-plugin相关的知识,希望对你有一定的参考价值。
maven-surefire-plugin Surefire 插件在test构建生命周期阶段用于执行应用程序的单元测试。
maven-surefire-plugin官网 (opens new window)
# 一、介绍
如果你执行过mvn test或者执行其他maven命令时跑了测试用例,你就已经用过maven-surefire-plugin了。 maven-surefire-plugin是maven里执行测试用例的插件,不显示配置就会用默认配置。 这个插件的surefire:test命令会默认绑定maven执行的test阶段。
如果你自己声明了,那么可以指定自己的版本,并且可以配置自定义的参数。
# 二、实践
# 2.1 用法
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M5</version>
</plugin>
</plugins>
</pluginManagement>
</build>
1
2
3
4
5
6
7
8
9
10
11
# 2.2 使用方法
mvn test
# 三、源码分析
# 3.1 学习目标
相关信息
框架整体比较复杂,但是对于我们有学习价值的东西不多,我们没必要太深入研究。在此只提几个关键的知识点学习。
- maven-surefire-plugin的常用参数及作用
- maven-surefire-plugin实现单测的原理
# 3.2 学习搭建环境
<!-- 先声明插件版本 -->
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<!-- JUnit 5 requires Surefire version 2.22.0 or higher -->
<version>2.22.0</version>
</plugin>
</plugins>
</build>
<!-- 然后引入依赖,方便debug跟进源码-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M5</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-core</artifactId>
<version>3.8.4</version>
</dependency>
<dependency>
<groupId>org.apache.maven.surefire</groupId>
<artifactId>surefire-junit4</artifactId>
<version>3.0.0-M5</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-plugin-api</artifactId>
<version>$dep.maven-api.version</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-model</artifactId>
<version>$dep.maven-api.version</version>
</dependency>
<dependency>
<groupId>org.apache.maven.plugin-tools</groupId>
<artifactId>maven-plugin-annotations</artifactId>
<version>$dep.maven-api.version</version>
</dependency>
<dependency>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-plugin-plugin</artifactId>
<version>$dep.maven-api.version</version>
</dependency>
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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# 3.3 找到插件入口
前面通过学习知道Mojo是运行的核心类,而SurefirePlugin就是Mojo的子类。 由此可知,如果要学习这个 maven-surefire-plugin
,入口就是在SurefirePlugin类。
# 四、 带着问题来学习
# 4.1 常用的参数都有那些
大多数为不常用的
是否常用 | 参数名 | 使用方法 | 解释 |
---|---|---|---|
常用 | skipTests | -D,或者xml配置标签 | 用于跳过单测 |
常用 | maven.test.skip.exec | -D,或者xml配置标签 | 用于跳过单测 |
常用 | maven.test.skip | -D,或者xml配置标签 | 用于跳过单测 |
不常用 | testClassesDirectory | xml配置标签 | 指定测试模块目录编译后目录 |
不常用 | maven.test.dependency.excludes | -D,或者xml配置标签 | 要排除的依赖,格式:groupId:artifactId |
不常用 | maven.test.additionalClasspath | -D,或者xml配置标签 | 追加classpath |
不常用 | project.build.testSourceDirectory | xml配置标签 | 指定测试模块目录源码目录 |
不常用 | excludes | xml配置 | 指定规则的类不需要被单测,eg: **/*Test.java |
不常用 | surefire.reportNameSuffix | -D,或者xml配置标签 | test报表后缀 |
不常用 | maven.test.redirectTestOutputToFile | -D,或者xml配置标签 | 运行的单侧输出重定向到report目录中 |
不常用 | failIfNoTests | -D,或者xml配置标签 | 如果没有单测就报错 |
不常用 | forkMode | -D,或者xml配置标签 | 运行模式 |
不常用 | jvm | -D,或者xml配置标签 | 指定jvm目录,如果不指定会读取系统 |
不常用 | argLine | -D,或者xml配置标签 | Jvm运行参数 |
不常用 | threadCount | -D,或者xml配置标签 | 线程数 |
不常用 | forkCount | -D,或者xml配置标签 | 指定启用多少个vm,1.5C 以数字结尾,数字乘以cpu核心数 |
不常用 | reuseForks | -D,或者xml配置标签 | 是否可重新使用forks进程 |
不常用 | disableXmlReport | -D,或者xml配置标签 | 禁用xml报告 |
不常用 | enableassertions | -D,或者xml配置标签 | 启用断言assert语句 |
forkMode 可设置值有 “never”, “once”, “always” 和 “pertest”。
- pretest: 每一个测试创建一个新进程,为每个测试创建新的JVM是单独测试的最彻底方式,但也是最慢的,不适合hudson上持续回归。
- once:在一个进程中进行所有测试。once为默认设置,在Hudson上持续回归时建议使用默认设置。
- always:在一个进程中并行的运行脚本,Junit4.7以上版本才可以使用,surefire的版本要在2.6以上提供这个功能,
# 4.2 知识点
// 大于等于2.0.0,小于2.1.2
VersionRange range = VersionRange.createFromVersionSpec("[2.0.0,2.1.2)");
System.out.println(range.containsVersion(new DefaultArtifactVersion("1.0")));
System.out.println(range.containsVersion(new DefaultArtifactVersion("2.0.0")));
System.out.println(range.containsVersion(new DefaultArtifactVersion("2.1.1")));
System.out.println(range.containsVersion(new DefaultArtifactVersion("2.1.2")));
System.out.println("------------");
VersionRange range2 = VersionRange.createFromVersionSpec("[2.0.0-M1SN,2.1.2)");
System.out.println(range2.containsVersion(new DefaultArtifactVersion("2.1.1-M2")));
1
2
3
4
5
6
7
8
9maven-surefire-plugin,用于自动化测试和单元测试的
如果你执行过mvn test或者执行其他maven命令时跑了测试用例,你就已经用过maven-surefire-plugin了。
maven-surefire-plugin是maven里执行测试用例的插件,不显示配置就会用默认配置。这个插件的surefire:test命令会默认绑定maven执行的test阶段。
2.maven-surefire-plugin的使用
2.1.1.插件自动匹配
最简单的配置方式就不配置或者是只声明插件。
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.19</version>
</plugin>
2.1.2.插件手动匹配
当然,如果你明确用的是JUnit4.7及以上版本,可以明确声明:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.19</version>
<dependencies>
<dependency>
<groupId>org.apache.maven.surefire</groupId>
<artifactId>surefire-junit47</artifactId>
<version>2.19</version>
</dependency>
</dependencies>
</plugin>
JUnit4.0(含)到JUnit4.7(不含)的版本,这样声明:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.19</version>
<dependencies>
<dependency>
<groupId>org.apache.maven.surefire</groupId>
<artifactId>surefire-junit4</artifactId>
<version>2.19</version>
</dependency>
</dependencies>
</plugin>
JUnit3.8(含)到JUnit4.0(不含)的版本,这样声明:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.19</version>
<dependencies>
<dependency>
<groupId>org.apache.maven.surefire</groupId>
<artifactId>surefire-junit3</artifactId>
<version>2.19</version>
</dependency>
</dependencies>
</plugin>
2.2.准备测试用例
我们现在准备两个类,一个被测试的类,一个测试用例.目录结构如下
现在我们准备一个简单的类.
package com.qyf404.learn.maven;
public class App
public int add(int a, int b)
return a + b;
public int subtract(int a, int b)
return a - b;
再创建一个测试用例.
package com.qyf404.learn.maven;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
public class AppTest
private App app;
@Before
public void setUp()
app = new App();
@Test
public void testAdd() throws InterruptedException
int a = 1;
int b = 2;
int result = app.add(a, b);
Assert.assertEquals(a + b, result);
@Test
public void testSubtract() throws InterruptedException
int a = 1;
int b = 2;
int result = app.subtract(a, b);
Assert.assertEquals(a - b, result);
@After
public void tearDown() throws Exception
2.3.用maven执行测试用例
用maven执行测试用例很简单,直接运行mvn test就可以.一般我们执行maven打包命令mvn package前maven会默认执行test命令.
3.进阶
后面让我们来研究一下maven-surefire-plugin这个插件更多的知识,这些多数都是和配置相关的.
3.1.跳过测试用例
在工作中,很多情况下我们打包是不想执行测试用例的,可能是测试用例不完事,或是测试用例会影响数据库数据.跳过测试用例执行过程有三个种方法.
3.1.1.在configuration中声明
在插件的configuration配置中声明跳过测试用例
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.19</version>
<dependencies>
<dependency>
<groupId>org.apache.maven.surefire</groupId>
<artifactId>surefire-junit47</artifactId>
<version>2.19</version>
</dependency>
</dependencies>
<configuration>
<skipTests>true</skipTests>
</configuration>
</plugin>
3.1.2.在properties中声明
在properties配置中声明跳过测试用例
<properties>
<maven.test.skip>true</maven.test.skip>
</properties>
或
<properties>
<skipTests>true</skipTests>
</properties>
3.1.3.在执行命令中声明
在执行maven命令时可以声明跳过测试用例
qyfmac$ mvn test -Dmaven.test.skip=true
或
qyfmac$ mvn test -DskipTests=true
3.1.4.跳过测试用例优先级排序
首先分两种情况,一种是配置skipTests,一种是配置maven.test.skip(真要命,声明位置就三处了,还搞出两个变量名,一共就是5中情况).
3.2.maven命令执行一个测试用例
很多情况下我们写完一个测试用例后,想马上运行一下,看看执行情况.如果用IDE开发,里面一般都有直接运行一个测试用例的方法.但是如果用maven命令达到同样的效果,就需要加些命令参数了.
比如我们现在再加一个测试用例App2Test.java.
package com.qyf404.learn.maven;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
@RunWith(JUnit4.class)
public class App2Test
private App app;
@Before
public void setUp()
app = new App();
@Test
public void testAdd() throws InterruptedException
int a = 1;
int b = 2;
int result = app.add(a, b);
Thread.currentThread().sleep(1000);
Assert.assertEquals(a + b, result);
@After
public void tearDown() throws Exception
直接运行 mvn test是这样的,它执行了全部测试用例.
现在我们用命令mvn test -Dtest=App2Test指定执行App2Test.
-Dtest的参数是可以用表达式的.
比如执行多个测试用例可以用逗号分开 mvn test -Dtest=App2Test,AppTest.
也可以用ant风格的路径表达式mvn test -Dtest=*2Test,mvn test -Dtest=???2Test.
甚至指定具体的测试方法mvn test -Dtest=*Test#testAdd.
指定具体包里的测试用例mvn test -Dtest=com/qyf404/learn/maven/*.
3.3.测试用例的包含与例外配置
上面说了,在执行命令时可以指定执行哪个或哪些测试用例,其实在pom.xml里也是可以配置的.
比如打包时执行测试用例AppTest,不执行App2Test,可以这么配置.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.19</version>
<dependencies>
<dependency>
<groupId>org.apache.maven.surefire</groupId>
<artifactId>surefire-junit47</artifactId>
<version>2.19</version>
</dependency>
</dependencies>
<configuration>
<!--配置是否跳过测试用例执行-->
<!--<skipTests>true</skipTests>-->
<includes>
<include>**/AppTest.java</include>
</includes>
<excludes>
<exclude>**/App2Test.java</exclude>
</excludes>
</configuration>
</plugin>
和里的配置方式和-Dtest后面的一样可以配置表达式:
指定具体类AppTest.
指定具体类AppTest.java.
指定具体类AppTest.class.
指定具体类com/qyf404/learn/maven/AppTest.class.
指定具体类com/qyf404/learn/maven/AppTest.class,App2Test.
叹号[!]表示否定!*2Test.class.
使用ant风格的路径表达式**/*Test.
使用ant风格的路径表达式**/???Test.
更复杂的%regex[expr]表达式%regex[com.qyf404.learn.maven.*Test.class].
更复杂的%regex[expr]表达式%regex[com.qyf404.*.*Test.class].
更复杂的%regex[expr]表达式%regex[com.qyf404.[learn|test].*Test.class],中间的方括号表示或的概念,即learn或test的情况.
更复杂的%regex[expr]表达式!%regex[com.qyf404.*.*2Test.class],这里面的叹号表示否定,即包含不符合该表达式的测试用例.
更复杂的%regex[expr]表达式%regex[.*2Test.class],这种配置方式忽略了包前缀,可以理解成倒着匹配全类名.
更复杂的%regex[expr]表达式里最好不要有问号[?],而且匹配的是类的全类名.
不可以指定具体方法,这种配置是错误的*Test#testAdd.
不可以指定java文件在%regex[expr]里具体方法,这种配置是错误的%regex[com.qyf404.learn.maven.*Test.java].
如果同时配置了和,最终执行的测试用例是二者的交集.
3.4.分组执行测试用例
上面我们说了,可以配置这些信息来控制执行哪些测试用例,但是JUnit里有个注解@Category可以对测试用例组分组标记,而用maven执行测试用例时,我们也可以根据这个注解的标记,来确定执行哪组测试用例.
比如我们的测试用例是这样的:
package com.qyf404.learn.maven;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.experimental.categories.Category;
public class AppTest
private App app;
@Before
public void setUp()
app = new App();
@Test
@Category(com.qyf404.learn.maven.FastTests.class)
public void testAdd() throws InterruptedException
int a = 1;
int b = 2;
int result = app.add(a, b);
System.out.println("---" + Thread.currentThread().getName());
Assert.assertEquals(a + b, result);
@Test()
@Category(com.qyf404.learn.maven.SlowTests.class)
public void testSubtract() throws InterruptedException
int a = 1;
int b = 2;
int result = app.subtract(a, b);
System.out.println("---" + Thread.currentThread().getName());
Assert.assertEquals(a - b, result);
@After
public void tearDown() throws Exception
pom.xml里这么配置:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.19</version>
<configuration>
<groups>com.qyf404.learn.maven.SlowTests</groups>
</configuration>
</plugin>
在执行mvn test时,则只执行标记@Category(com.qyf404.learn.maven.SlowTests.class)的测试用例.
3.5.若有测试执行失败则跳过其他测试
在打包时,默认情况会执行全部测试用例,然后给出一个执行的统计结果,如下所示:
Results :
Tests run: 3, Failures: 1, Errors: 0, Skipped: 0
很多情况下我们希望测试用例没有失败的才能打包,如果出现打包失败,需要立刻停止执行其他测试用例.为满足这个要求,我们需要增加一些配置设定.
<configuration>
<skipAfterFailureCount>1</skipAfterFailureCount>
</configuration>
里面的数字1表示当有一个测试用例执行失败或发生异常时,跳过后续的其他测试用例.这个数字其实只要是一个大于零的数就可以.表达的意思就是当有N个测试用例执行失败或异常时,跳过后续的其他测试用例.
3.6.重新运行失败的测试用例
当我们的一个测试用例测试的是一个远程服务,在某些情况下可能由于环境问题(比如网络)导致测试用例执行失败,但这并不是程序问题.换句话说,当一个测试用例执行N次,有一次执行成功就认为成功.这个时候我们就需要配置一个参数,运行执行失败的此时用例重新执行.
<configuration>
<rerunFailingTestsCount>2</rerunFailingTestsCount>
</configuration>
里面的数字2表示当某个测试用例执行失败以后,还可以重新执行2次,有一次执行成功就认为测试用例执行成功.里面的2只要是一个大于零的整数就可以,表示重试次数.如果发生重试,在maven的执行报告中会多一个Flakes.
3.7.Debugging Tests
一般情况我们可以在IDE中直接执行测试用例,有时候会出现这种情况,IED中直接执行测试用例是没问题的,但是用maven命令打包时就执行失败了.我们可以在命令中加入-X或–debug来打印更多的日志信息来排查问题.但也可以开启JVM的调试端口来远程debug.
3.7.1.以调试模式执行maven命令
执行maven命令mvn -Dmaven.surefire.debug test以开启调试模式.当然也可以用完整的命令来指定端口
mvn -Dmaven.surefire.debug="-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005 -Xnoagent -Djava.compiler=NONE" test
命令执行后是这个样子:
qyfmac$ mvn -Dmaven.surefire.debug test
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building learn-maven 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ learn-maven ---
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] skip non existing resourceDirectory /Users/qyfmac/git/learn-maven/src/main/resources
[INFO]
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ learn-maven ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ learn-maven ---
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] skip non existing resourceDirectory /Users/qyfmac/git/learn-maven/src/test/resources
[INFO]
[INFO] --- maven-compiler-plugin:3.1:testCompile (default-testCompile) @ learn-maven ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] --- maven-surefire-plugin:2.19:test (default-test) @ learn-maven ---
-------------------------------------------------------
T E S T S
-------------------------------------------------------
Listening for transport dt_socket at address: 5005
后面我们就需要根据这个5005端口去启动本地源码了.
3.7.2.使用IDE远程调试
开始调试前需要先配置IDE,我以idea为例说明如何配置.
在右上角选择Edit Configurations…
在打开的对话框中选择左上角的加号,然后选择Remote.
配置远程调试的参数,主要就是改个名字和端口,其他的配置一般不需要修改.设定好后点保存
在要debug得测试用例上设置一个断点.
选择刚才设置好的配置启动远程调试.
开始debug你的程序吧.
3.8.并发执行测试用例
如果测试用例很多,而且并行执行时不会互相影响,这时我们可以配置一个线程数来加快测试用例的执行效率.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.19</version>
<configuration>
<parallel>methods</parallel>
<threadCount>10</threadCount>
</configuration>
</plugin>
3.9.查看测试报告
在执行完mvn test后,会在target目录下生成测试报告
最后:下方这份完整的软件测试视频学习教程已经整理上传完成,朋友们如果需要可以自行免费领取 【保证100%免费】
以上是关于maven-surefire-plugin的主要内容,如果未能解决你的问题,请参考以下文章