1. 程式人生 > >maven外掛之maven之maven-surefire-plugin

maven外掛之maven之maven-surefire-plugin

1.maven-surefire-plugin是個什麼鬼?

如果你執行過 mvn test 或者執行其他maven命令時跑了測試用例,你就已經用過 maven-surefire-plugin 了。 maven-surefire-plugin 是maven裡執行測試用例的外掛,不顯示配置就會用預設配置。這個外掛的 surefire:test 命令會預設繫結maven執行的 test 階段。

maven的生命週期有哪些階段?

[validate, initialize, generate-sources, process-sources, generate-resources, process-resources, compile, process-classes, generate-test-sources, process-test-sources, generate-test-resources, process-test-resources, test-compile, process-test-classes, test

 , prepare-package, package, pre-integration-test, integration-test, post-integration-test, verify, install, deploy]

2.maven-surefire-plugin的使用

如果說maven意見有了maven-surefire-plugin的預設配置,我們還有必要了解maven-surefire-plugin的配置麼?答案是肯定的。雖說maven-surefire-plugin有預設配置,但是當需要修改一些測試執行的策略時,就有必要我們去重新配置這個外掛了。

2.1.配置JUnit

2.1.1.外掛自動匹配

最簡單的配置方式就不配置或者是隻宣告外掛。

    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <version>2.19</version>
    </plugin>

這個時候maven-surefire-plugin會按照如下邏輯去尋找JUnit的版本並執行測試用例。

if the JUnit version in the project >= 4.7 and the parallel attribute has ANY value
    use junit47 provider
if JUnit >= 4.0 is present
    use junit4 provider
else
    use junit3.8.1

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>

JUnit3.8以下的版本surefire不支援。建議大家用最新的JUnit版本,目前是4.12.

<dependencies>
    [...]
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
        <scope>test</scope>
    </dependency>
    [...]        
</dependencies>

本文的例子我們用的Junit4.12.

2.2.準備測試用例

我們現在準備兩個類,一個被測試的類,一個測試用例.目錄結構如下

現在我們準備一個簡單的類.

package com.qyf404.learn.maven;

public class App {
    publicintadd(int a, int b) {
        return a + b;
    }
    publicintsubtract(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
    publicvoidsetUp() {
        app = new App();
    }
    @Test
    publicvoidtestAdd() throws InterruptedException {
        int a = 1;
        int b = 2;
        int result = app.add(a, b);
        Assert.assertEquals(a + b, result);
    }
    @Test
    publicvoidtestSubtract() throws InterruptedException {
        int a = 1;
        int b = 2;
        int result = app.subtract(a, b);
        Assert.assertEquals(a - b, result);
    }
    @After
    publicvoidtearDown() throws Exception {
    }
}

2.3.用maven執行測試用例

用maven執行測試用例很簡單,直接執行 mvn test 就可以.一般我們執行maven打包命令 mvn package 前maven會預設執行 test 命令.

qyfmac$ mvn 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] Changes detected - recompiling the module!
[WARNING] File encoding has not been set, using platform encoding UTF-8, i.e. build is platform dependent!
[INFO] Compiling 1 source file to /Users/qyfmac/git/learn-maven/target/classes
[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] Changes detected - recompiling the module!
[WARNING] File encoding has not been set, using platform encoding UTF-8, i.e. build is platform dependent!
[INFO] Compiling 2 source files to /Users/qyfmac/git/learn-maven/target/test-classes
[INFO] 
[INFO] --- maven-surefire-plugin:2.19:test (default-test) @ learn-maven ---
[WARNING] The parameter forkMode is deprecated since version 2.14. Use forkCount and reuseForks instead.
[INFO] Surefire report directory: /Users/qyfmac/git/learn-maven/target/surefire-reports
[INFO] Using configured provider org.apache.maven.surefire.junit4.JUnit4Provider

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running com.qyf404.learn.maven.AppTest
Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.003 sec - in com.qyf404.learn.maven.AppTest

Results :

Tests run: 2, Failures: 0, Errors: 0, Skipped: 0

[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 2.622 s
[INFO] Finished at: 2015-12-01T11:36:04+08:00
[INFO] Final Memory: 14M/228M
[INFO] ------------------------------------------------------------------------
qyfmac$ 

其實我們會發現關鍵內容還是JUnit的東西,maven只是作為一個呼叫器呼叫了一下這些測試用例.

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

  • skipTests 和 maven.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是這樣的,它執行了全部測試用例.

qyfmac$ mvn test
[INFO] Scanning for projects...
[INFO]                                                                         
[INFO] ------------------------------------------------------------------------
[INFO] Building learn-maven 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------

...

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running com.qyf404.learn.maven.App2Test
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 1.004 sec - in com.qyf404.learn.maven.App2Test
Running com.qyf404.learn.maven.AppTest
Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0 sec - in com.qyf404.learn.maven.AppTest

Results :

Tests run: 3, Failures: 0, Errors: 0, Skipped: 0

[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 2.773 s
[INFO] Finished at: 2015-12-01T14:57:00+08:00
[INFO] Final Memory: 9M/156M
[INFO] ------------------------------------------------------------------------

現在我們用命令 mvn test -Dtest=App2Test 指定執行App2Test.

qyfmac$ mvn test -Dtest=App2Test
[INFO] Scanning for projects...
[INFO]                                                                         
[INFO] ------------------------------------------------------------------------
[INFO] Building learn-maven 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------

...

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running com.qyf404.learn.maven.App2Test
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 1.003 sec - in com.qyf404.learn.maven.App2Test

Results :

Tests run: 1, Failures: 0, Errors: 0, Skipped: 0

[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 3.061 s
[INFO] Finished at: 2015-12-01T14:58:59+08:00
[INFO] Final Memory: 9M/156M
[INFO] ------------------------------------------------------------------------

-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