一、 需求介紹
自動化測試,尤其是接口測試時,要寫大量的測試用例,這些測試用例我們當然首選使用TesteNG編寫,用例數量大,還涉及各種依賴包之類的問題,因此用Maven管理也是最方便最易實現的。
面臨的問題是:
TestNG的模式,在IDE中運行很方便,這個做法在開發測試用例的時候是必走的步驟,因為對於測試用例本身的代碼,我們也需要調試測試,讓它沒有BUG,才能用它測試別人的代碼或者接口從命令行上運行TestNG,如果是個普通的Java工程,指定一個CLASSPATH,然后把所有的依賴JAR包放進去即可通過java -cp my_class_path org.testng.TestNG testng.xml運行,然而這種方式不能解決依賴項和版本沖突的問題,對於大團隊多項目的情況並不適用在Maven工程中,我們如果將所有測試用例寫到/src/test/java目錄中,只需要使用mvn test命令就可以運行了,也使用Maven解決了各種依賴問題,但是這個時候如果要進行測試用例的轉移交流,我們只能使用工程源代碼,因為使用mvn package打出來的包中,是沒有測試代碼的,無法拿出去交流或者部署到命令行上以CLI的方式單獨運行
針對以上問題,我們只需要將TestNG和Maven進行深度捆綁,就可以輕松解決,同時我們引入ReportNG,讓測試報告更加美觀一些。
完成這些過程,再將工程部署到Jenkins上去,就能同時實現手動調度、自動調度、任務觸發、遠程調度。而且,開發階段在IDE中調試測試不影響,使用IDE的機制運行測試用例可以全部運行(在測試用例類上點擊右鍵選擇運行這種方式),使用Maven的機制可以使用testng.xml的所有配置策略(比如支付接口只測試冪等接口而不測試非冪等的)。所有問題全部解決。
二、配置實現
2.1 首先引入TestNG
在pom.xml中加入對TestNG的依賴項,這個很簡單了:
-
<dependency>
-
<groupId>org.testng</groupId>
-
<artifactId>testng</artifactId>
-
<version>6.10</version>
-
</dependency>
2.2 完成Maven與TestNG的捆綁
在pom.xml的build->plugins節點下添加下面的內容:
-
<plugin>
-
<groupId>org.apache.maven.plugins</groupId>
-
<artifactId>maven-surefire-plugin</artifactId>
-
<version>2.20.1</version>
-
<configuration>
-
<suiteXmlFiles>
-
<suiteXmlFile>testng.xml</suiteXmlFile>
-
</suiteXmlFiles>
-
</configuration>
-
</plugin>
這樣就可以實現Maven運行test命令時按照TestNG的testng.xml配置運行相應的測試用例,運行mvn test指令即可。
2.3 引入ReportNG
這一步是在第二步的基礎上,但是要完成這一步,我們首先要在工程中加入對ReportNG的依賴:
-
<!-- 依賴velocity -->
-
<dependency>
-
<groupId>velocity</groupId>
-
<artifactId>velocity-dep</artifactId>
-
<version>1.4</version>
-
</dependency>
-
-
<!-- 依賴Guice -->
-
<dependency>
-
<groupId>com.google.inject</groupId>
-
<artifactId>guice</artifactId>
-
<version>3.0</version>
-
<scope>test</scope>
-
</dependency>
-
-
<!-- 依賴reportNg 關聯testNg -->
-
<dependency>
-
<groupId>org.uncommons</groupId>
-
<artifactId>reportng</artifactId>
-
<version>1.1.5</version>
-
<scope>test</scope>
-
<exclusions>
-
<exclusion>
-
<groupId>org.testng</groupId>
-
<artifactId>testng</artifactId>
-
</exclusion>
-
</exclusions>
-
</dependency>
ReportNG官方提供的ReportNG JAR包從Maven中央倉庫中是可以使用的,版本號是1.1.4(2013年之后沒再更新了),但是它對報告中的中文處理有問題,會亂碼,所以我改了它的源代碼之后重新編譯了(順便改了它的groupId,以避免和官方的混淆不清,讓別人誤會以為官方又出新版本了呢),但是它是一個Ant工程而不是Maven工程,我編譯完成之后沒有上傳到公司的Nuxus私服庫,所以使用的是本地依賴,那么ReportNG本身又有對velocity和guice這兩個東西有依賴,那就得一起加上吧。事實上如果不加,是會報錯的。
加入了工程對ReportNG的依賴之后,我們就使用它對已經與Maven捆綁的TestNG配置進行個性化,如下所示:
-
<plugin>
-
<groupId>org.apache.maven.plugins</groupId>
-
<artifactId>maven-surefire-plugin</artifactId>
-
<version>2.20.1</version>
-
<configuration>
-
<suiteXmlFiles>
-
<suiteXmlFile>testng.xml</suiteXmlFile>
-
</suiteXmlFiles>
-
<properties>
-
<!-- Setting ReportNG listeners -->
-
<property>
-
<name>listener</name>
-
<value>org.uncommons.reportng.HTMLReporter,
-
org.uncommons.reportng.JUnitXMLReporter
-
</value>
-
</property>
-
</properties>
-
</configuration>
-
</plugin>
2.4 集成打包
完成上面三步之后,我們就可以使用了,然而還有一個問題,就是這個Maven工程打包成Jar之后仍然不能直接在命令行上運行,必須依賴於Maven正確安裝的情況下使用mvn test命令才能在命令行上運行,那么我們進一步改造它。
其實很簡單,只需要使用maven-shade-plugin這個插件就可以輕松實現,我們在pom.xml的build->plugins節點下添加下面的內容:
這樣的配置,是指定在調用mvn package指令的時候,就可以完成打包,打的包中包含了依賴項,可以獨立運行,我是這樣運行的:
java -jar target\sinopec-lmk-1.0.1.jar testng.xml
有一點需要強調一下:
測試用例要寫到/src/main/java目錄下,如果寫到/src/test/java下,是不起作用的。
3. 附加信息
3.1 對於Maven與TestNG捆綁,還有更詳細的文檔
Maven官方給出的詳細用法,文檔鏈接:http://maven.apache.org/surefire/maven-surefire-plugin/examples/testng.html
還有一篇文章對Maven與TestNG的用法也做了詳細的介紹,文檔鏈接:http://howtodoinjava.com/testng/how-to-execute-testng-tests-with-maven-build/
3.2 maven-shade-plugin插件的應用
Maven官方也給出了詳細的用法介紹,文檔鏈接:https://maven.apache.org/plugins/maven-shade-plugin/usage.html
3.3 TestNG並發運行測試注意事項
這幾點是我在使用它的時候總結出來的,供大家參考:
3.3.1 TestNG注解BeforeTest和BeforeClass的區別
最開始使用的時候,我一直以為BeforeTest是運行測試方法之前執行,BeforeClass是加載測試類的時候執行,事實上不是的。
BeforeTest是在TestNG啟動測試任務之前執行,AfterTest是在TestNG完成測試任務之后執行。
BeforeClass是在運行測試方法之前執行,AfterClass是在運行測試方法之后執行。
3.3.2 線程數的控制及對測試的影響
在testng.xml中,我們可以配置並行運行的策略,以及線程的數量,我經過多次嘗試,發現parallel設置為classes是比較合理的,因為創建線程開銷也很大,一個類一個線程已經比較奢侈了。
另外啟用並行運行測試時,建議設置preserve-order的值為false,也就是不按照預定順序運行,會是亂序的,這有助於我們多次運行測試用例時發現不同的問題。
還有,如果啟用並行測試,BeforeTest和AfterTest是在主線程中運行的,而BeforeClass和AfterClass是在測試類所在的線程中運行的,這很重要