Maven通過Maven Surefire Plugin插件執行單元測試。(通過Maven Failsafe Plugin插件執行集成測試)
在pom.xml中配置JUnit,TestNG測試框架的依賴,即可自動識別和運行src/test目錄下利用該框架編寫的測試用例。surefire也能識別和執行符合一定命名約定的普通類中的測試方法(POJO測試)。
生命周期中test階段默認綁定的插件目標就是surefire中的test目標,無需額外配置,直接運行mvn test就可以。
基本配置如下,下文中的配置項如無特殊說明,都位於pom文件的<configuration>節點中。
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>2.18.1</version> <configuration> ......
配置內容
...... </configuration> </plugin>
常用通用配置
- 跳過測試階段
<skipTests>true</skipTests>
或者
mvn install -DskipTests
或者 (Compliler插件也會根據該參數跳過編譯測試類)
mvn install -Dmaven.test.skip=true
- 忽略測試失敗
Maven在測試階段出現失敗的用例時,默認的行為是停止當前構建,構建過程也會以失敗結束。有時候(如測試驅動開發模式)即使測試出現失敗用例,仍然希望能繼續構建項目。
<testFailureIgnore>true</testFailureIgnore>
或者
mvn test -Dmaven.test.failure.ignore=true
- 包含和排除特定的測試類
surefire默認的查找測試類的模式如下:
-
- **/Test*.java
- **/*Test.java
- **/*TestCase.java
自定義包含和排除模式,支持ant-style表達式和 正則表達式(%regex[...], 按.class文件匹配而不是.java)
<includes> <include>Sample.java</include> <include>%regex[.*[Cat|Dog].*Test.*]</include> </includes>
<excludes> <exclude>**/TestCircle.java</exclude> <exclude>**/TestSquare.java</exclude> </excludes>
- 運行指定的用例
指定測試類
mvn -Dtest=TestClassName test mvn -Dtest=TestCi*le test mvn -Dtest=TestSquare,TestCi*le test
指定單個測試類中的多個方法(Junit4+, TestNG)
mvn -Dtest=TestCircle#mytest test mvn -Dtest=TestCircle#test* test mvn -Dtest=TestCircle#testOne+testTwo test #(Surefire2.12.1+, Junit4.x+)
- 並發執行測試
(mvn命令加-T選項,多模塊項目的各個模塊可以並行構建。)
兩個方式:
方法一是使用parallel 參數,在一個進程中執行多個線程。
Junit4.7+可用值有:methods, classes, both(classesAndMethods), suites, suitesAndClasses, suitesAndMethods, classAndMethods, all。Junit Runner必須繼承自orig.junit.runners.ParentRunner或為指定@org.junit.runner.RunWith。
線程數配置:useUnlimitedThreads 為true,不限制線程數。useUnlimitedThreads 為false時可以使用threadCount和perCoreThreadCount參數。還可以通過threadCountSuites,threadCountClasses,threadCountMethods在不同粒度限制線程。parallelTestsTimeoutInSeconds和parallelTestsTimeoutForcedInSeconds參數設置線程的超時時間。Junit中@NotThreadSafe注解的內容會單線程執行,避免並發。
方法二是使用forkCount參數,創建多個測試進程。
如果forkCount參數值后加C,表示乘以CPU核數(如forkCount=2.5C)。reuseForks表示一個測試進程執行完了之后是殺掉還是重用來繼續執行后續的測試。 默認配置為forkCount=1/reuseForks=true。進程的測試單元是class,逐個class的傳遞給測試進程。
可以用systemPropertyVariables 傳入系統參數(mvn test -D...或配置元素),也可以使用argLine傳入JVM選項。argLine或者systemPropertyVariables配置里中也能用${surefire.forkNumber}占位符,代表每個進程自己的fork編號(1...n),用來向每個進程傳入獨立的資源配置(forkCount=0時,該占位符值為1)。
如果使用-T n同時執行多個mvn模塊,每個模塊都會有forkCount個進程,${surefire.forkNumber}的值為1..n*forkCount。
surefire2.14之前的版本使用forkMode進行配置,對應關系如下。
Old Setting | New Setting |
forkMode=once (default) | forkCount=1 (default), reuseForks=true (default) |
forkMode=always | forkCount=1 (default), reuseForks=false |
forkMode=never | forkCount=0 |
forkMode=perthread, threadCount=N | forkCount=N, (reuseForks=false, if you did not had that one set) |
多種並行方式組合
只要forkCount不為0,就可以和-T組合。
forkCount=0, 或forkCount=1/reuseForks=true,可以和parallel自由組合。
forkCount的測試進程是按類為單位執行的,測試類整個整個的傳到測試進程中執行。reuseForks=false或forkCount>1時,就會使用獨立的測試進程,所以parallel=classes就失效了。但是還是可以組合parallel=methods/threadCount=n指定每個測試進程里的並發線程數。
其他不常用的配置列在最后。
POJO測試
- 不使用測試框架,直接編寫名稱為**/*Test類,其中的test*方法也會被surefire執行。
- 類中定義的public void setUp()和public void tearDown()方法也會被surefire識別。
- 驗證可使用JAVA assert關鍵字。
- 無法並發執行。
TestNG
- TestNG默認查找執行test包下的*Test.java。Pom.xml中添加TestNG依賴就能執行testng測試。
- 指定SuiteXML文件
<suiteXmlFiles> <suiteXmlFile>testng.xml</suiteXmlFile> </suiteXmlFiles>
- 為TestNG @Parameters 注解提供參數
<systemPropertyVariables> <propertyName>firefox</propertyName> </systemPropertyVariables>
- 指定group
<groups>functest,perftest</groups>
- 指定Listeners和Reporters
TestNG支持在測試時附加自定義的listener, reporter, annotation transformer, method interceptor。默認會使用基本的listener生成HTML和XML報告。
Listener實現org.testng.ITestListener接口,會在測試開始、通過、失敗等時刻實時發送通知。
Reporter實現org.testng.IReporter接口,在整個測試運行完畢之后才會發送通知,參數為對象列表,包含整個測試的執行結果狀況。
<properties> <property> <name>usedefaultlisteners</name> <value>false</value> <!-- disabling default listeners is optional --> </property> <property> <name>listener</name> <value>com.mycompany.MyResultListener,com.mycompany.MyAnnotationTransformer,com.mycompany.MyMethodInterceptor</value> </property> <property> <name>reporter</name> <value>listenReport.Reporter</value> </property> </properties>
JUnit
Pom.xml中添加JUnit依賴就能執行Junit測試。
根據引入的Junit依賴版本和是否配置了並發 自動確定使用JUnit 3.8.x, JUnit 4.x (serial provider) 還是 JUnit 4.7(junit-core provider with parallel support),也可以在<plugin>節點里加入<dependencies>元素強行指定執行版本。(詳細說明:http://maven.apache.org/surefire/maven-surefire-plugin/examples/junit.html)
- 指定Listener(JUnit4+)
<properties> <property> <name>listener</name> <value>com.mycompany.MyResultListener,com.mycompany.MyResultListener2</value> </property> </properties>
- 指定Categories(Junit4.8+)。分組可以用在測試方法或測試類上。Junit使用接口和類的類型分組,選擇注解為@Category(基類)的分組時,所有注解了@Category(子類)的分組也會被選中。
<groups>com.mycompany.SlowTests</groups>
public interface SlowTests{} public interface SlowerTests extends SlowTests{} public class AppTest { @Test @Category(com.mycompany.SlowTests.class) public void testSlow() { System.out.println("slow"); } @Test @Category(com.mycompany.SlowerTests.class) public void testSlower() { System.out.println("slower"); } @Test @Category(com.cmycompany.FastTests.class) public void testSlow() { System.out.println("fast"); } }
- Security Manager
<argLine>-Djava.security.manager -Djava.security.policy=${basedir}/src/test/resources/java.policy</argLine>
Junit3還可以如下配置(forkCount為0時):
<systemPropertyVariables> <surefire.security.manager>java.lang.SecurityManager</surefire.security.manager> </systemPropertyVariables>
其他不常用的通用配置
- 失敗重跑
mvn -Dsurefire.rerunFailingTestsCount=2 test #(JUnit需要4.x版本)
重跑的log和報告等詳細信息,看這里http://maven.apache.org/surefire/maven-surefire-plugin/examples/rerun-failing-tests.html
- 指定VM參數
<argLine>-Djava.endorsed.dirs=...</argLine>
- 系統屬性
<systemPropertyVariables> <propertyName>propertyValue</propertyName> <buildDirectory>${project.build.directory}</buildDirectory> [...] </systemPropertyVariables>
不再推薦使用的方式
<systemProperties> <property> <name>buildDir</name> <value>String類型的值</value> </property> </systemProperties>
繼承父項目配置的系統屬性
<systemProperties combine.children="append"> <property> [...] </property> </systemProperties>
- 配置Classpath
test classpath包括:
-
- test-classes/
- classes/
- 項目依賴
- 額外配置的classpath元素
要配置classpath,最好是使用添加依賴的方法。如果一定添加額外的ClassPath,這樣配置:
<additionalClasspathElements> <additionalClasspathElement>path/to/additional/resources</additionalClasspathElement> <additionalClasspathElement>path/to/additional/jar</additionalClasspathElement> </additionalClasspathElements>
移除依賴
<classpathDependencyExcludes> <classpathDependencyExcludes>org.apache.commons:commons-email</classpathDependencyExcludes> </classpathDependencyExcludes>
按scope移除依賴
<classpathDependencyScopeExclude>runtime</classpathDependencyScopeExclude>
-
- compile - system, provided, compile
- runtime - compile, runtime
- test - system, provided, compile, runtime, test
- 調試
默認情況下,surefire在新的進程中執行,命令mvn -Dmaven.surefire.debug test創建的測試進程會等待遠程調試器(Eclipse)連接到5005端口。要配置不同的端口命令為:
mvn -Dmaven.surefire.debug="-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -Xnoagent -Djava.compiler=NONE" test
如果forkCount選項配置為0(mvn -DforkCount=0 test),不會創建新的測試進程,測試在maven主線程中執行。命令mvnDebug -DforkCount=0 test會使maven以調試模式運行,可以將遠程調試器連接到maven進程。
- 選擇測試框架Provider
可選的有surefire-junit3, surefire-junit4, surefire-junit47和 surefire-testng。指定Provider時,測試框架的依賴配置也不能少。
maven-surefire-plugin的<plugin>節點中添加如下配置。
<dependencies> <dependency> <groupId>org.apache.maven.surefire</groupId> <artifactId>surefire-junit47</artifactId> <version>2.18.1</version> </dependency> </dependencies>
- ClassLoader相關配置
解決classpath長度超過命令行運行的最大參數長度問題。
方法有兩個,各有優缺點:
一是使用獨立的類加載器,在其中加載classpath內容。
二是使用一個只有META-INF/MANIFEST.MF的jar文件(如booter.jar),在manifest.mf文件中配置classpath。然后以 java -classpath booter.jar MyApp的方式運行。
配置方法
useSystemClassLoader為fasle, 使用獨立的類加載器。
useSystemClassLoader為true並且useManifestOnlyJar為true時 ,使用manifest-only JAR
useSystemClassLoader為true並且useManifestOnlyJar為false時,使用最原始的java classpath
執行
mvn -Dsurefire.useSystemClassLoader=false test
或
<useSystemClassLoader>false</useSystemClassLoader> <useManifestOnlyJar>false</useManifestOnlyJar>
這一部分具體信息可查看:http://maven.apache.org/surefire/maven-surefire-plugin/examples/class-loading.html