定义
maven-surefire-plugin是一个用于mvn生命周期的测试阶段的插件(本文假设读者已经掌握了Maven相关知识点),可以通过一些参数设置方便的在testNG或junit下对测试阶段进行自定义。在实际工作中我们可以利用该插件指定运行的测试用例,并通过多线程的方式来运行用例,更为方便的是它还可以控制重新运行失败的测试用例的次数,这为持续集成过程中的代码测试工作带来了极大方便!
在pom.xml配置方式
这里以配置junit为例,最简单的配置方式就是只声明插件。
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version> 3.0.0-M4</version>
</plugin>
此时maven-surefire-plugin会按照如下逻辑去寻找JUnit的版本并执行测试用例。
if the JUnit version in the project >= 4.7 and the parallel attributehas ANY value
use junit47 provider
if JUnit >= 4.0 is present
use junit4 provider
else
use junit3.8.1
备注:surefire plugin 不支持junit3.8以下版本
插件手动配置方式如下:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M4</version>
<dependencies>
<dependency>
<groupId>org.apache.maven.surefire</groupId>
<artifactId>surefire-junit47</artifactId>
<version>3.0.0-M4</version>
</dependency>
</dependencies>
</plugin>
常用的功能包括
跳过测试阶段
<skipTests>true</skipTests>
忽略测试失败
Maven在测试阶段出现失败的用例时,默认的行为是停止当前构建,构建过程也会以失败结束。有时候(如测试驱动开发模式)即使测试出现失败用例,仍然希望能继续构建目。
<testFailureIgnore>true</testFailureIgnore>
包含和排除特定的测试类
surefire默认的查找测试类的模式如下:
**/Test*.java
**/*Test.java
**/*TestCase.java
自定义包含和排除模式,支持ant-style表达式和 正则表达式(%regex[...],按.class文件匹配而不是.java)
<includes>
<include>%regex[.*[Demo1|Demo2].*Test.*]</include>
</includes>
<excludes>
<exclude>**/DemoTest1.java</exclude>
<exclude>**/DemoTest2.java</exclude>
</excludes>
分组执行测试
Junit中可以实现用例的分组测试,即运行测试用例时只执行某一类别(具备某一标签)的测试用例,实现方式如下:
首先定义一个接口,作为分组标签
public interfaceSmokeTests{
}
用例中使用SmokeTests分组标签
@Test
@Category(SmokeTests.class)
public void test2()
{
try {
Thread.sleep(1000);
}catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
assertEquals(1,1);
}
Suite中使用分组标签
@RunWith(Categories.class)
@IncludeCategory(SmokeTests.class)
@SuiteClasses({Test1.class, Test2.class, Test3.class, Test4.class, Test5.class, Test6.class })
public classSomokeTests {
}
Pom中配置如下:
<groups>com.my.demo.SmokeTests</groups>
并发执行测试
使用parallel 参数,在一个进程中执行多个线程。Junit4.7+可用参数包括:methods, classes, both(classesAndMethods), suites, suitesAndClasses,suitesAndMethods, classAndMethods, all。
重新运行失败的测试用例
当我们的一个测试用例测试的是一个远程服务,在某些情况下可能由于环境问题(比如网络)导致测试用例执行失败,但这并不是程序问题.换句话说,当一个测试用例执行N次,有一次执行成功就认为成功.这个时候我们就需要配置一个参数,运行执行失败的此时用例重新执行.
<rerunFailingTestsCount>2</rerunFailingTestsCount>
若有测试执行失败则跳过其他测试
很多情况下我们希望测试用例没有失败的才能打包,如果出现打包失败,需要立刻停止执行其他测试用例.为满足这个要求,我们需要增加一些配置设定.
<skipAfterFailureCount>1</skipAfterFailureCount>
应用实例
首先,在Eclipse 的Maven工程中创建Junit测试用例,代码如下:
public class Test1 {
@Before
public void setUp()throws Exception {
}
@After
public voidtearDown() throws Exception {
}
@Test
public void test1()
{
try {
Thread.sleep(1000);
}catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
assertEquals(1,2);
}
@Test
public void test2()
{
try {
Thread.sleep(1000);
}catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
assertEquals(1,1);
}
@Test
public void test3()
{
try {
Thread.sleep(1000);
}catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
assertEquals(11,11);
}
}
以同样的形式创建测试用例2和测试用例3,创建一个suite包括Test1、Test2和Test3
@RunWith(Suite.class)
@SuiteClasses({Test1.class, Test2.class, Test3.class })
public classAllTests {
}
然后,配置pom.xml,如下:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M4</version>
<dependencies>
<dependency>
<groupId>org.apache.maven.surefire</groupId>
<artifactId>surefire-junit47</artifactId>
<version>3.0.0-M4</version>
</dependency>
</dependencies>
<configuration>
<!--配置是否跳过测试用例执行-->
<!--配置用例运行入口-->
<includes>
<include>**/AllTests.java</include>
</includes>
<!--配置用例失败后运行次数-->
<rerunFailingTestsCount>2</rerunFailingTestsCount>
<!--配置用例并行方案以及线程数-->
<parallel>classes</parallel>
<threadCount>3</threadCount>
</configuration>
</plugin>
</plugins>
</build>
最后,在Eclipse中 运行Maven install
eclipse构建maven项目运行详情如下: 从日志中可以看到AllTests.java作为了测试入口、com.my.test.Test3.test1、com.my.test.Test2.test1、com.my.test.Test3.test1失败后又被执行了2次,3个线程构建的执行时间为10.582 s(本机测试单线程执行构建需要22.079 s)
INFO]
-------------------------------------------------------
[INFO] T E S T S
[INFO]
-------------------------------------------------------
[INFO] Running com.my.test.Test3
[ERROR]
Tests run: 3, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 3.004 s
<<< FAILURE! - in com.my.test.Test3
[ERROR]com.my.test.Test3.test1 Time elapsed:1.002 s <<< FAILURE!
java.lang.AssertionError:
expected:<1> but was:<2>
at com.my.test.Test3.test1(Test3.java:27)
[INFO] Running com.my.test.Test1
[ERROR]
Tests run: 3, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 3.004 s
<<< FAILURE! - in com.my.test.Test1
[ERROR]com.my.test.Test1.test1 Time elapsed:1.003 s <<< FAILURE!
java.lang.AssertionError:
expected:<1> but was:<2>
at com.my.test.Test1.test1(Test1.java:27)
[INFO] Running com.my.test.Test2
[ERROR]
Tests run: 3, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 3.004 s
<<< FAILURE! - in com.my.test.Test2
[ERROR]com.my.test.Test2.test1 Time elapsed:1.003 s <<< FAILURE!
java.lang.AssertionError:
expected:<1> but was:<2>
at com.my.test.Test2.test1(Test2.java:28)
[INFO] Running com.my.test.Test3
[ERROR]
Tests run: 1, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 1 s
<<< FAILURE! - in com.my.test.Test3
[ERROR]com.my.test.Test3.test1 Time elapsed: 1s <<< FAILURE!
java.lang.AssertionError:
expected:<1> but was:<2>
at com.my.test.Test3.test1(Test3.java:27)
[INFO] Running com.my.test.Test1
[ERROR]
Tests run: 1, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 1 s
<<< FAILURE! - in com.my.test.Test1
[ERROR]com.my.test.Test1.test1 Time elapsed: 1s <<< FAILURE!
java.lang.AssertionError:
expected:<1> but was:<2>
at com.my.test.Test1.test1(Test1.java:27)
[INFO] Running com.my.test.Test2
[ERROR]
Tests run: 1, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 1 s
<<< FAILURE! - in com.my.test.Test2
[ERROR]com.my.test.Test2.test1 Time elapsed: 1s <<< FAILURE!
java.lang.AssertionError:
expected:<1> but was:<2>
at com.my.test.Test2.test1(Test2.java:28)
[INFO] Running com.my.test.Test3
[ERROR]
Tests run: 1, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 1.001 s
<<< FAILURE! - in com.my.test.Test3
[ERROR]com.my.test.Test3.test1 Time elapsed:1.001 s <<< FAILURE!
java.lang.AssertionError:
expected:<1> but was:<2>
at com.my.test.Test3.test1(Test3.java:27)
[INFO] Running com.my.test.Test1
[ERROR]
Tests run: 1, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 1.001 s
<<< FAILURE! - in com.my.test.Test1
[ERROR]com.my.test.Test1.test1 Time elapsed: 1.001s <<< FAILURE!
java.lang.AssertionError:
expected:<1> but was:<2>
at com.my.test.Test1.test1(Test1.java:27)
[INFO] Running com.my.test.Test2
[ERROR]
Tests run: 1, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 1.001 s
<<< FAILURE! - in com.my.test.Test2
[ERROR]com.my.test.Test2.test1 Time elapsed:1.001 s <<< FAILURE!
java.lang.AssertionError:
expected:<1> but was:<2>
at com.my.test.Test2.test1(Test2.java:28)
[INFO]
[INFO]
Results:
[INFO]
[ERROR]
Failures:
[ERROR]
com.my.test.Test1.test1
[ERROR] Run 1: Test1.test1:27 expected:<1> butwas:<2>
[ERROR] Run 2: Test1.test1:27 expected:<1> butwas:<2>
[ERROR] Run 3: Test1.test1:27 expected:<1> butwas:<2>
[INFO]
[ERROR]
com.my.test.Test2.test1
[ERROR] Run 1: Test2.test1:28 expected:<1> butwas:<2>
[ERROR] Run 2: Test2.test1:28 expected:<1> butwas:<2>
[ERROR] Run 3: Test2.test1:28 expected:<1> butwas:<2>
[INFO]
[ERROR]
com.my.test.Test3.test1
[ERROR] Run 1: Test3.test1:27 expected:<1> butwas:<2>
[ERROR] Run 2: Test3.test1:27 expected:<1> butwas:<2>
[ERROR] Run 3: Test3.test1:27 expected:<1> butwas:<2>
[INFO]
[INFO]
[ERROR]
Tests run: 9, Failures: 3, Errors: 0, Skipped: 0
[INFO]
[INFO]
------------------------------------------------------------------------
[INFO]
BUILD FAILURE
[INFO]
------------------------------------------------------------------------
[INFO]
Total time: 10.582 s
[INFO]
Finished at: 2019-12-09T11:23:14+08:00
[INFO]
Final Memory: 13M/226M
[INFO] ------------------------------------------------------------------------
网友评论