Maven的生命周期:
講解Maven測試篇之前將首先介紹一下Maven生命周期的相關概念,如果你熟知這部分概念可以略過此小節內容。
通常,我們在構建一個項目的時候,不外乎是對其進行清理、編譯、測試和部署等操作。對於大多數項目,我們每次都要重復這些必要的過程,而Maven正是對這些必要的構建過程進行了抽象,它以項目的清理、初始化、編譯、測試、打包、部署等構建步驟作為項目生命周期的各個階段。
每個Maven項目,都有三個相互獨立的生命周期,其中包括:
- clean生命周期:負責項目的清理工作;
- default生命周期:負責項目的部署;
- site生命周期:負責創建項目的文檔站點;
其中各個生命周期又包含不同的階段(如下圖所示),例如clean生命周期下有pre-clean、clean和post-clean三個階段,分別負責項目清理前的工作、清理上次構建的項目和項目清理后的工作,這些階段是順序執行的,也就是說,當你執行pre-clean階段的時候,clean和post-clean階段不會被執行,當你執行clean階段的時候,pre-clean階段和clean階段會被執行,post-clean階段不會被執行,當你執行post-clean階段時候,pre-clean、clean和post-clean這三個階段都會依次被執行。同理,default生命周期和site生命周期下也分為各個不同的階段,這些階段和clean生命周期下的各個階段一樣,后面階段的執行依賴於前面的階段執行。
Maven生命周期及生命周期下的階段示意圖
此時你可能認為,當執行default生命周期下的某個階段時,clean生命周期下的所有階段也會被執行,其實並非這樣。正如之前所說,Maven項目的每個生命周期是相互獨立的,執行某個生命周期下的某個階段,不會對另外兩個生命周期下的任何階段產生影響。
如果要對Maven生命周期下的某個階段進行調用,運行相應的Maven命令即可。例如,調用clean生命周期下的clean階段,運行如下命令:
mvn clean
此時clean 生命周期下的pre-clean和clean階段將被執行。
如果要調用default 生命周期下的package階段,運行如下命令:
mvn package
此時在default生命周期內,package階段之前所有的階段將被執行,package階段也將被執行。
如果要對項目進行打包,在項目打包之前可能需要對項目上一次的構建進行刪除清理,運行如下命令:
mvn clean package
此時在clean生命周期內,clean階段之前所有的階段將被執行,clean階段也將被執行。default生命周期內package階段之前所有的階段和package階段也將被執行。
如果要執行項目測試,運行如下命令:
mvn test
此時在default生命周期內,test階段之前所有的階段將被執行,test階段也將被執行。
Maven的每個階段都綁定了一個或多個插件,調用某個階段時,具體任務將交由這個階段所綁定的插件來完成。比如進行項目測試時,需要調用default生命周期下的test階段,但具體任務將是交由“maven-surefire-plugin”插件完成的,因為test階段與“maven-surefire-plngin”插件進行了綁定。這個“maven-surefire-plngin” 插件就是一個測試運行器,它與主流的測試框架(Junit3、Junit4和TestNG)進行了集成。
引用“maven-surefire-plngin”插件依賴
因為“maven-surefire-plngin”插件是Maven內置綁定的,即使你不在“pom.xml”文件中對”maven-surefire-plngin”插件做相關配置,調用default生命周期的test階段時,Maven也會使用“maven-surefire-plngin”插件執行相關任務。當然你還可以在“pom.xml”文件中自定義配置這個插件:
<project> [...] <build> <pluginManagement> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>2.20</version> </plugin> </plugins> </pluginManagement> </build> [...] </project>
整合TestNG
使用TestNG作為測試框架時,需要在Maven項目的“pom.xml”文件中配置TestNG依賴,這里需要在<scope/>元素中將TestNG的依賴范圍配置為test。
<dependencies> [...] <dependency> <groupId>org.testng</groupId> <artifactId>testng</artifactId> <version>6.9.8</version> <scope>test</scope> </dependency> [...] </dependencies>
你還可以在項目路徑下創建一個“testng.xml”文件,這個文件主要用來描述測試套件和測試執行相關參數的配置,但它不是TesgNG必須的配置文件,如果你沒有創建“testng.xml”文件,也就不需要對“maven-surefire-plngin”插件做“testng.xml”文件的相關配置。
<!DOCTYPE suite SYSTEM "http://beust.com/testng/testng-1.0.dtd" > <suite name="testSuite"> <test name="test"> <classes> <class name=“ATest" /> </classes> </test> </suite>
上面是以一份簡要的“testng.xml”配置文件,它首先定義了一個名稱為“testSuite”的測試套件,這個測試套件內包含一個測試名稱為“test”的測試,這個測試指定了一個“ATest”測試類,“ATest”類是一個簡單的TestNG測試類,清單如下:
import org.testng.Assert; import org.testng.annotations.Test; public class ATest { @Test public void testIsTrue(){ A a=new A(); Assert.assertTrue(a.returnTrue()); } }
在“maven-surefire-plngin”插件中引入“testng.xml”文件,只需要在“pom.xml”文件中添加如下配置:
<project> [...] <build> <pluginManagement> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>2.20</version> <configuration> <suiteXmlFiles> <suiteXmlFile>testng.xml</suiteXmlFile> </suiteXmlFiles> </configuration> </plugin> </plugins> </pluginManagement> </build> […] </project>
這里主要介紹了Maven與TestNG的整合相關配置,有關TestNG更詳細的教程請參閱官方文檔。
約定優於配置:
在默認情況下,“maven-surefire-plugin”插件將自動執行項目“src/test/java”路徑下的測試類,但測試類需要遵從以下命名模式,Maven才能自動執行它們:
- Test*.java :以Test開頭的Java類;
- *Test.java :以Test結尾的Java類;
- *TestCase.java:以TestCase結尾的Java類;
跳過測試:
如果要求Maven跳過測試,在Maven命令行中加入skipTests參數即可:
mvn package -DskipTests
執行以上命令之后,Maven會在構建日志中打印跳過測試執行的信息:


除了執行Maven 命令時指定參數來跳過測試,還可通過在“pom.xml”文件中通過配置“maven-surefire-plugin”插件來跳過測試:
<project> [...] <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>2.20</version> <configuration> <skipTests>true</skipTests> </configuration> </plugin> </plugins> </build> [...] </project>
再次通過“mvn package”命令對項目進行構建,打印日志如下:
如果不僅要跳過測試類的執行,還要臨時性的跳過測試代碼編譯,可以執行以下命令:
mvn package -Dmaven.test.skip=true
此時項目構建的日志中顯示沒有對測試代碼進行編譯,並且跳過了測試類的執行:
Dmaven.test.skip=true 參數控制了“maven-compiler-plugin” 和“maven-surefire-plugin” 兩個插件的行為,在項目構建過程中跳過了測試代碼的編譯和測試。此外,還可以通過配置“pom.xml”文件,完成與上述執行Maven命令同樣的效果:
<project> [...] <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>2.5.1</version> <configuration> <skip>true</skip> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>2.20</version> <configuration> <skipTests>true</skipTests> </configuration> </plugin> </plugins> </build> [...] </project>
動態指定要運行的測試類:
在進行單元測試時,有時候不需要執行項目中所有的測試類,“maven-surefire-plugin”插件支持命令中設置Dtest參數,來執行指定的測試類。例如只執行“ATest” 測試類:
mvn -Dtest=ATest test
”maven-surefire-plugin“插件還支持使用星號匹配測試類名的方式以指定運行特定的測試類,星號表示匹配零個或多個字符。例如只執行”A“開頭的測試類:
mvn -Dtest=A* test
除了使用星號匹配,還可以使用逗號指定多個測試類:
mvn test -Dtest=ATest,BTest
同時匹配類名以A開頭的測試類和類名為BTest的測試類:
mvn -Dtest=A*,BTest test
當test命令通過參數匹配不到任何測試類時,項目將會構建失敗。配置參數DfailIfNoTests=false可以在匹配不到測試類時依舊構建成功:
mvn -Dtest=AATest -DfailIfNoTests=false test
使用DfailIfNoTests=false參數也是另一種跳過測試的方法。“maven-surefire-plugin”插件並沒有提供通過指定測試類的類名來跳過執行某個測試類的命令,但可以通過在“pom.xml”文件中進行排除指定的測試類。
包含與排除測試用例:
<include/>元素配置的測試類名將會被執行:
<project> [...] <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>2.20</version> <configuration> <includes> <include>**/*Tests.java</include> </includes> </configuration> </plugin> </plugins> </build> [...] </project>
其中“ **/*Tests.java”匹配以Tests結尾的Java類,其中兩個星號用來表示匹配任意路徑,一個星號用來匹配路徑風格符除外的零個或多個字符。
使用<excludes/>元素中排除執行匹配到的測試類:
<project> [...] <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>2.20</version> <configuration> <excludes> <exclude>**/CTest.java</exclude> <exclude>**/DTest.java</exclude> </excludes> </configuration> </plugin> </plugins> </build> [...] </project>
參考資料:
Maven文檔:http://maven.apache.org/guides/
maven-surefire-plugin 文檔:http://maven.apache.org/surefire/maven-surefire-plugin/
=====================================================================
結束: 歡迎給我留言
