(十二)maven-surefire-plugin,用於自動化測試和單元測試的


原文鏈接:https://www.bbsmax.com/A/n2d9WPwJDv/

1.簡介

如果你執行過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中情況).

    • 如果是配置skipTests, configuration的配置優先級最高,命令中得配置次之, properties的配置最低.

    • configuration > 命令 > properties

    • 如果是配置maven.test.skip,命令中得配置優先級最高, properties的配置最低.

      命令 > properties

    • skipTestsmaven.test.skip有一個被設置成了true,則跳過測試用例.

      skipTests||maven.test.skip決定是否跳過測試用例執行.

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>

<include><exclude>里的配置方式和-Dtest后面的一樣可以配置表達式:

  • 指定具體類<include>AppTest</include>.

  • 指定具體類<include>AppTest.java</include>.

  • 指定具體類<include>AppTest.class</include>.

  • 指定具體類<include>com/qyf404/learn/maven/AppTest.class</include>.

  • 指定具體類<include>com/qyf404/learn/maven/AppTest.class,App2Test</include>.

  • 嘆號[!]表示否定<include>!*2Test.class</include>.

  • 使用ant風格的路徑表達式<include>**/*Test</include>.

  • 使用ant風格的路徑表達式<include>**/???Test</include>.

  • 更復雜的%regex[expr]表達式<include>%regex[com.qyf404.learn.maven.*Test.class]</include>.

  • 更復雜的%regex[expr]表達式<include>%regex[com.qyf404.*.*Test.class]</include>.

  • 更復雜的%regex[expr]表達式<include>%regex[com.qyf404.[learn|test].*Test.class]</include>,中間的方括號表示或的概念,即learn或test的情況.

  • 更復雜的%regex[expr]表達式<include>!%regex[com.qyf404.*.*2Test.class]</include>,這里面的嘆號表示否定,即包含不符合該表達式的測試用例.

  • 更復雜的%regex[expr]表達式<include>%regex[.*2Test.class]</include>,這種配置方式忽略了包前綴,可以理解成倒着匹配全類名.

  • 更復雜的%regex[expr]表達式里最好不要有問號[?],而且匹配的是類的全類名.

  • 不可以指定具體方法,這種配置是錯誤的<include>*Test#testAdd</include>.

  • 不可以指定java文件在%regex[expr]里具體方法,這種配置是錯誤的<include>%regex[com.qyf404.learn.maven.*Test.java]</include>.

  • 如果同時配置了<include><exclude>,最終執行的測試用例是二者的交集.

3.4.分組執行測試用例

上面我們說了,可以配置<include>這些信息來控制執行哪些測試用例,但是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為例說明如何配置.

  1. 在右上角選擇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目錄下生成測試報告

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM