TestNG
是一個測試框架,其靈感來自 JUnit
和 NUnit
,但同時引入了一些新的功能,使其功能更強大,使用更方便。html
TestNG
設計涵蓋全部類型的測試:單元,功能,端到端,集成等,它須要 JDK5
或更高的 JDK
版本。java
詳細使用說明請參考官方連接:https://testng.org/doc/index.html數組
在 maven 中引入依賴:多線程
<dependency> <groupId>org.testng</groupId> <artifactId>testng</artifactId> <version>6.10</version> </dependency>
簡單示例:併發
(1)被測試 HelloWorld 類框架
package study.testng; public class HelloWorld { public String hello(){ return "hello world !"; } }
(2)測試類 TestHelloWorld 類maven
package study.testng; import org.testng.Assert; import org.testng.annotations.Test; public class TestHelloWorld { //測試返回結果不爲空 @Test public void tester1(){ HelloWorld hello = new HelloWorld(); String helloworld = hello.hello(); Assert.assertNotNull(helloworld); } //測試返回結果爲」hello world !「字符串 @Test public void tester2(){ HelloWorld hello = new HelloWorld(); String helloworld = hello.hello(); System.out.println(helloworld); Assert.assertEquals(helloworld, "hello world !"); } }
(3)測試結果ide
[TestNG] Running: C:\Users\Administrator\.IntelliJIdea2019.2\system\temp-testng-customsuite.xml hello world ! =============================================== Default Suite Total tests run: 2, Failures: 0, Skips: 0 ===============================================
凡是在類方法中添加了 @Test
註解的就是咱們須要測試的方法函數
默認是 true
, 若是設置爲 false
,則在運行時不會執行這個測試方法;學習
示例:
package com.ggf.testng.annotation; import org.testng.annotations.Test; /** * @Description: 忽略測試,能夠經過@Test的註解的enable屬性來配置是否執行用例方法 * enable默認值爲 true,須要設置爲false纔會跳過這個測試用例 * @Author: ggf * @Date: 2019/12/29 */ public class IgnoreTest { @Test public void ignore1() { System.out.println("ignore1 run..."); } @Test(enabled = false) public void ignore2() { System.out.println("ignore2 run ..."); } @Test public void ignore3() { System.out.println("ignore3 run ..."); } }
運行結果:
[TestNG] Running: C:\Users\Administrator\.IntelliJIdea2019.2\system\temp-testng-customsuite.xml ignore1 run... ignore3 run ... =============================================== Default Suite Total tests run: 2, Failures: 0, Skips: 0 ===============================================
@Test(expectedExceptions = ClassName.class)
若是 ClassName
類拋出了異常,測算測試經過,沒有異常算測試不經過;
expectedExceptions
的值也能夠是一個數組:
@Test(expectedExceptions = {ClassName.class, ClassName2.class,... })
示例:
package com.ggf.testng.annotation; import org.testng.annotations.Test; /** * @Description: 異常測試 * @Author: ggf * @Date: 2019/12/29 * * 何時會用到異常測試?? * 在咱們指望結果爲某一個異常的時候 * 好比:咱們傳入了某些不合法的參數,程序拋出了異常 * 也就是說個人指望結果就是這個異常。 */ public class ExpectedException { /** * 運行時異常,咱們指望返回一個運行時異常,這條用例纔是正確的。 */ @Test(expectedExceptions = RuntimeException.class, enabled = false) public void runTimeExceptionFailed() { System.out.println("沒有拋出異常,這條用例不經過!"); } /** * 結果拋出了一個運行時異常,和咱們的指望一致,測試經過。 */ @Test(expectedExceptions = RuntimeException.class) public void runTimeExceptionSuccess() { System.out.println("程序拋出了運行時異常,測試用例經過!"); throw new RuntimeException(); } }
運行結果:
[TestNG] Running: C:\Users\Administrator\.IntelliJIdea2019.2\system\temp-testng-customsuite.xml 程序拋出了運行時異常,測試用例經過! =============================================== Default Suite Total tests run: 1, Failures: 0, Skips: 0 ===============================================
在被依賴的方法運行完成以後運行當前方法,若是依賴方法測試不經過,那麼當前方法也不會繼續運行了;依賴的方法能夠有多個;
例:@Test(dependsOnMethods = { "methodName1" , 「methodName2」 })
示例:
package com.ggf.testng.annotation; import org.testng.annotations.Test; /** * @Description: 方法直接的依賴測試 * @Author: ggf * @Date: 2019/12/29 */ public class DependTest { @Test public void test1() { System.out.println("test1 run ..."); } /** * test2運行時,須要依賴test1的運行 * 若是test1運行失敗,會直接忽略test2, test2就不會執行了。 */ @Test(dependsOnMethods = {"test1"}) public void test2() { System.out.println("test2 run ..."); } }
把在一個<test>
標籤內的中全部類方法再進行組,在運行時,一個組的方法會一塊兒運行,而後再運行下一個組的方法;
分組的最小維度爲方法,當把帶分組的@Test(groups = 」groupName」)註解對類使用時,這個測試類中的全部方法都屬於這同一個組;
一個方法也能夠同時屬於多個組,@Test(groups = {「groupName1」, 「groupName2」}),那麼每組運行時這個方法都會被執行一次;
同一個組裏的方法類,若是分別屬於兩個不一樣的測試用例(<test>
)內,那麼它們其實能夠算兩個組,它們會在每一個測試用例分別運行,而不會合在一塊兒運行;
示例:
package com.ggf.testng.groups; import org.testng.annotations.AfterGroups; import org.testng.annotations.BeforeGroups; import org.testng.annotations.Test; import javax.sound.midi.Soundbank; /** * @Description: 對測試用例方法進行分組,能夠對一組中的數據進行初始化 * @Author: ggf * @Date: 2019/12/29 */ public class GroupsOnMethod { @BeforeGroups(groups = "server") public void beforeGroupsOnServer() { System.out.println("服務端組運行前執行的方法。。。"); } @BeforeGroups(groups = "client") public void beforeGroupsOnClient() { System.out.println("客戶端組運行前執行的方法。。。"); } @Test(groups = "server") public void test1() { System.out.println("server test1 run ...."); } @Test(groups = "server") public void test2() { System.out.println("server test2 run ...."); } @Test(groups = "client") public void test3() { System.out.println("client test3 run ...."); } @Test(groups = "client") public void test4() { System.out.println("client test4 run ...."); } @AfterGroups(groups = "server") public void afterGroupsOnServer() { System.out.println("服務端組運行以後執行的方法。。。"); } @AfterGroups(groups = "client") public void afterGroupsOnClient() { System.out.println("客戶端組運行以後執行的方法。。。"); } }
運行結果:
[TestNG] Running: C:\Users\Administrator\.IntelliJIdea2019.2\system\temp-testng-customsuite.xml 服務端組運行前執行的方法。。。 server test1 run .... server test2 run .... 服務端組運行以後執行的方法。。。 客戶端組運行前執行的方法。。。 client test3 run .... client test4 run .... 客戶端組運行以後執行的方法。。。 =============================================== Default Suite Total tests run: 4, Failures: 0, Skips: 0 ===============================================
@Test(timeOut = 3000) 設置超時時間,單位爲毫秒。
示例:
package com.course.testng; import org.testng.annotations.Test; public class TimeOutTest { /** * 單位爲毫秒值,3秒內沒有響應,就證實失敗了,反之成功 * @throws InterruptedException */ @Test(timeOut = 3000) public void testSuccess() throws InterruptedException { Thread.sleep(2000); } @Test(timeOut = 2000) public void testFailed() throws InterruptedException { Thread.sleep(3000); } }
運行結果:
[TestNG] Running: C:\Users\Administrator\.IntelliJIdea2019.2\system\temp-testng-customsuite.xml org.testng.internal.thread.ThreadTimeoutException: Method com.course.testng.TimeOutTest.testFailed() didn't finish within the time-out 2000 =============================================== Default Suite Total tests run: 2, Failures: 1, Skips: 0 ===============================================
屬性名 | 描述 |
---|---|
alwaysRun | 設置爲 true 時,不管什麼狀況都會運行 |
dataProvider | 數據提供者的名稱 |
dataProviderClass | 若是未指定,將在當前測試方法的類或其父類之一上查找數據提供者。 若是指定了此屬性,則數據提供者方法在指定的類上必須是靜態的。 |
dependsOnGroups | 依賴的組列表 |
dependsOnMethods | 依賴的方法列表 |
description | 說明 |
enabled | 默認爲true,設置爲 false 時失效 |
expectedExceptions | 預期測試方法將引起的異常列表。 若是未引起任何異常或與該列表中的異常不一樣,則此測試將標記爲失敗。 |
groups | 所屬組 |
invocationCount | 調用次數 |
invocationTimeOut | 全部 invocationCount 的累積超時時間。 注意:若是未指定 nvocationCount,則將忽略此屬性。 |
priority | 此測試方法的優先級 |
successPercentage | 該方法預期成功的百分比 |
singleThreaded | 若是設置爲 rue,則即便當前正在使用 parallel =「 methods」 運行測試,也保證該測試類上的全部方法均可以在同一線程中運行。 此屬性只能在類級別使用,若是在方法級別使用,則將被忽略。 |
timeOut | 超時時間 |
threadPoolSize | 此方法的線程池的大小。 該方法將從 invocationCount 指定的多個線程中調用。 注意:若是未指定 invocationCount,則忽略此屬性 |
註解 | 描述 |
---|---|
@BeforeSuite | 在該套件的全部測試都運行在註釋的方法以前,僅運行一次(套件測試是一塊兒運行的多個測試類)。 |
@AfterSuite | 在該套件的全部測試都運行在註釋方法以後,僅運行一次。 |
@BeforeClass | 在調用當前類的第一個測試方法以前運行,註釋方法僅運行一次。 |
@AfterClass | 在調用當前類的第一個測試方法以後運行,註釋方法僅運行一次。 |
@BeforeTest | 註釋的方法將在屬於<test> 標籤內的類的全部測試方法運行以前運行。 |
@AfterTest | 註釋的方法將在屬於<test> 標籤內的類的全部測試方法運行以後運行。 |
@BeforeGroups | 配置方法將在以前運行組列表。 此方法保證在調用屬於這些組中的任何一個的第一個測試方法以前不久運行。 |
@AfterGroups | 此配置方法將在以後運行組列表。該方法保證在調用屬於任何這些組的最後一個測試方法以後不久運行。 |
@BeforeMethod | 註釋方法將在每一個測試方法以前運行。 |
@AfterMethod | 註釋方法將在每一個測試方法以後運行。 |
@Parameters | 描述如何將參數傳遞給@Test方法。 |
@DataProvider | 標記一種方法來提供測試方法的數據。 註釋方法必須返回一個Object [] [],其中每一個Object []能夠被分配給測試方法的參數列表。 要從該DataProvider接收數據的@Test方法須要使用與此註釋名稱相等的dataProvider名稱。 |
@Factory | 將一個方法標記爲工廠,返回TestNG將被用做測試類的對象。 該方法必須返回Object []。 |
@Listeners | 定義測試類上的偵聽器。 |
@Test | 將類或方法標記爲測試的一部分。 |
示例:
測試類 TestConfig.java
package study.testng; import org.testng.annotations.AfterGroups; import org.testng.annotations.AfterMethod; import org.testng.annotations.AfterSuite; import org.testng.annotations.AfterTest; import org.testng.annotations.BeforeGroups; import org.testng.annotations.BeforeMethod; import org.testng.annotations.BeforeSuite; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; public class TestConfig { @BeforeSuite public void beforeSuite() { System.out.println("測試套件(當前xml中<suite>標籤)以前運行@BeforeSuite--------------------"); } @AfterSuite public void afterSuite() { System.out.println("測試套件(當前xml中<suite>標籤)以後運行@AfterSuite--------------------\n"); } @BeforeTest public void beforeTest() { System.out.println("測試用例(當前xml中<test>標籤)以前運行@BeforeTest----------"); } @AfterTest public void afterTest() { System.out.println("測試用例(當前xml中<test>標籤)以後運行@AfterTest----------\n"); } @BeforeMethod public void beforeMethod() { System.out.println("當前類每一個測試方法(@Test)以前運行@BeforeMethod"); } @AfterMethod public void AfterMethod(){ System.out.println("當前類每一個測試方法(@Test)以後運行@AfterMethod"); } @BeforeGroups(value="group1") public void beforeGroups(){ System.out.println("配置組配group1以前運行@BeforeGroups.................."); } @AfterGroups(value="group1") public void afterGroups(){ System.out.println("配置組配group1以前運行@AfterGroups.................."); } @Test public void test1(){ System.out.println("runnig TestConfig.test1()"); } @Test(groups = "group1") public void test2(){ System.out.println("runnig TestConfig.test2()"); } @Test(groups = "group1") public void test3(){ System.out.println("runnig TestConfig.test3()"); } }
新建一個自定義 xml 配置文件 tester.xml (maven項目將該文件建立在 resource 目錄下)
<?xml version="1.0" encoding="UTF-8"?> <!-- @BeforeSuite --> <suite name="tester"> <!-- @BeforeTest --> <test name="case1"> <classes> <class name="study.testng.TestConfig" /> <class name="study.testng.TestHelloWorld" /> </classes> </test> <!-- @AfterTest --> <!-- @BeforeTest --> <test name="case2"> <classes> <class name="study.testng.TestConfig" /> </classes> </test> <!-- @AfterTest --> </suite> <!-- @AfterSuite -->
運行結果:
從這個結果顯示出註釋的做用位置。其中 @BeforeGroups
和 @AfterGroups
的做用範圍是能夠跨類的,但類必須是在同一個測試用例(<test>
標籤)範圍內;
這些標籤的運行前後順序能夠總結爲:
@BeforeSuite->@BeforeTest->@BeforeClass->{@BeforeMethod->@Test->@AfterMethod}->@AfterClass->@AfterTest->@AfterSuite(其中{}內的與多少個@Test,就循環執行多少次)。
<?xml version="1.0" encoding="UTF-8"?> <!--添加dtd約束文件,標籤自動提示--> <!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" > <suite> <suite-files> <suite-file path=""></suite-file> </suite-files> <parameter name="" value=""></parameter> <method-selectors> <method-selector> <selector-calss name=""></selector-calss> </mehod-selector> </method-selectors> <test name=""> <parameter name="" value=""><parameter> <groups> <define name=""> <include name=""/> <exclude name=""/> </define> <run> <include name=""/> <exclude name=""/> </run> </groups> <classes> <class name=""> <mehods> <parameter name="" value=""></parameter> <include name=""></include> <exclude name=""></exclude> </methods> </class> <class></class> </classes> <packages> <package name=""> <include name=""></include> <exclude name=""></exclude> </package> </packages> <listeners> <listener class-name=""/> </listenters> </test> <test></test> </suite>
<suite>
標籤說明:一個xml文件只能有一個<suite>
, 是一個xml文件的根級
<suite>
由 <test>
和 <parameters>
組成
標籤屬性說明:
屬性 | 說明 | 使用方法 | 參數值 |
---|---|---|---|
name | 必選項,
|
name="XXX" | suite名字 |
junit | 是否執行Junit模式(識別setup()等) | junit="true" | true和false,默認false |
verbose | 控制檯輸出的詳細內容等級,0-10級(0無,10最詳細) | verbose="5" | 0到10 |
parallel | 是否在不一樣的線程並行進行測試,要與thread-count配套使用 | parallel="mehods" | 詳見表格下內容,默認false |
parent-module | 和Guice框架有關,只運行一次,建立一個parent injector給全部guice injectors | ||
guice-stage | 和Guice框架有關 | guice-stage="DEVELOPMENT" | DEVELOPMENT,PRODUCTION,TOOL,默認"DEVELOPMENT" |
configfailurepolicy | 測試失敗後是再次執行仍是跳過,值skip和continue | configfailurepolicy="skip" | skip、continue,默認skip |
thread-count | 與parallel配套使用,線程池的大小,決定並行線程數量 | thread-count="10" | 整數,默認5 |
annotations | 獲取註解,值爲javadoc時,使用JavaDoc的註釋;不然用JDK5註釋 | annotations="javadoc" | javadoc |
time-out | 設置parallel時,終止執行單元以前的等待時間(毫秒) | time-out="10000" | 整數,單位毫秒 |
skipfailedinvocationcounts | 是否跳過失敗的調用 | skipfailedinvocationcounts="true" | true和false,默認false |
data-provider-thread-count | 併發時data-provider的線程池數量 | data-provider-thread-count="5" | 整數 |
object-factory | 一個實現IObjectFactory接口的類,實例化測試對象 | object-factory="classname" | 類名 |
allow-return-values | 是否容許返回函數值 | all-return-values="true" | true和false |
preserve-order | 是否按照排序執行 | preserve-order="true" | true和false,默認true |
group-by-instances | 按照實例分組 | group-by-instances="true" | true和false,默認false |
parallel
屬性詳細說明
該參數的值false
,methods
,tests
,classes
,instances
。默認false
parallel
必須和 thread-count
配套使用,不然至關於無效參數,thread-count
決定了並行測試時開啓的線程數量
parallel="mehods"
TestNG將並行執行全部的測試方法在不一樣的線程裏
parallel="tests"
TestNG將並行執行在同一個<test>
下的全部方法在不一樣線程裏
parallel="classes"
TestNG將並行執行在相同<class>
下的方法在不一樣線程裏
parallel="instances"
TestNG將並行執行相同實例下的全部方法在不一樣的縣城裏
parent-module
和guice-stage
和 Guice
框架有關,testNG 6對 Guice
框架提供了支持,我沒用過這個框架,因此這兩個參數沒看懂╮(╯▽╰)╭
<suite-files>
標籤說明:引入外部的xml文件(地址由path參數決定,path必填項),將引入的xml與當前的xml文件一塊兒使用
聲明方法:
<suite-files> <suite-file path="/path/suitefile1"></suite-file> </suite-files>
<test>
標籤說明:一個<suite>
下能夠有多個<test>
,能夠經過<suite>
的parallel="tests"
來進行並行測試,必須和thread-count
配套使用,不然是無效參數
<test>
由<parameters>、<groups>、<classes>
三部分組成
標籤屬性說明:
參數 | 說明 | 使用方法 | 參數值 |
---|---|---|---|
name | test的名字,將出如今報告裏 | name="testname" | test的名字 |
junit | 是否按照Junit模式運行 | junit="true" | true和false,默認false |
verbose | 控制檯輸出的詳細內容等級,0-10級(0無,10最詳細),不在報告顯示 | verbose="5" | 0到10 |
parallel | 是否在不一樣的線程並行進行測試,要與thread-count配套使用 | parallel="mehods" | 與suite的parallel一致,默認false |
thread-count | 與parallel配套使用,線程池的大小,決定並行線程數量 | thread-count="10" | 整數,默認5 |
annotations | 獲取註解,值爲javadoc時,使用JavaDoc的註釋;不然用JDK5註釋 | annotations="javadoc" | javadoc |
time-out | 設置parallel時,終止執行單元以前的等待時間(毫秒) | time-out="10000" | 整數,單位毫秒 |
enabled | 標記是否執行這個test | enabled="true" | true和false,默認true |
skipfailedinvocationcounts | 是否跳過失敗的調用 | skipfailedinvocationcounts="true" | true和false,默認false |
preserve-order | 是否按照排序執行,若是是true,將按照xml文件中的順序去執行 | preserve-order="true" | true和false,默認true |
allow-return-values | 是否容許返回函數值 | all-return-values="true" | true和false,默認false |
<parameter>
標籤說明:提供測試數據,有name和value兩個參數
聲明方法:<parameter name = "parameter_name" value = "parameter_value "/>
testng.xml
文件中的<parameter>
能夠聲明在<suite>
或者<test>
級別,在<test>
下的<parameter>
會覆蓋在<suite>
下聲明的同名變量
<groups>
標籤說明:要運行的組,能夠自定義一個組,能夠包括要執行的,還排除要執行的方法。必須和<classes>
配套使用,從下面的類中找到對應名字的方法
<groups>
由<difine>
和 <run>、<dependencies>
三部分組成。
<diffine>
能夠將 group 組成一個新組,包括要執行和不執行的大組;
<run>
要執行的方法;
<dependencies>
指定了某 group 須要依賴的 group(好比下面的例子,group1 須要依賴 group2 和 group3 先執行)。
聲明方法:
<groups> <define name ="all"> <include name ="testgroup1"/> </define> <run> <include name ="testmethod1"/> <exclude name="testmethod2"/> </run> <dependencies> <group name ="group1" depends-on="goup2 group3"/> </dependencies> </groups>
<classes>
標籤說明:方法選擇器,要執行的方法寫在這裏,參數有name和priority。
註釋:
1.<classes>
下必須寫要執行的<class>
,不然不會執行任何內容,若是填寫了 class 沒有寫 methods,會按照填寫的 class 的下的註釋 @Test 去執行全部的方法
2.<classes>
下的<methods>
若是填寫了<include>
,那隻會執行所填寫的方法,沒有填寫的方法不會去執行
聲明方法:
<classes> <class name="要執行的class名"> <methods> <include name ="要執行的方法名"></include> </methods> </class> </classes>
(1)建立測試類:PatamterTest.java
package com.ggf.testng.paramter; import org.testng.annotations.Parameters; import org.testng.annotations.Test; /** * @Description: testNG的參數化配置,經過xml文件進行方法的賦值操做 * @Author: ggf * @Date: 2019/12/29 */ public class PatamterTest { @Test @Parameters({"name","age"}) public void showInfo(String name, int age) { System.out.println("name="+ name + " age=" + age); } }
(2)建立配置文件
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" > <suite name="paramterTest"> <test name="transfer"> <classes> <class name="com.ggf.testng.paramter.PatamterTest"/> <parameter name="name" value="張三"/> <parameter name="age" value="11"/> </classes> </test> </suite>
(3)運行結果:
[TestNG] Running: D:\workspace\testwork\testNGDemo\src\main\resources\paramter.xml name=張三 age=11 =============================================== paramterTest Total tests run: 1, Failures: 0, Skips: 0 ===============================================
示例:
package com.ggf.testng.paramter; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import java.util.HashMap; import java.util.Map; /** * @Description: 主要是對DataProvider註解的學習,經過這個註解的標識,來給測試類進行賦值。 * @Author: ggf * @Date: 2019/12/29 * 首先定義一個數據源的方法,經過@DataProvider註解來標識。 * 而後定義一個測試方法,經過@Test(dataProvider="")屬性來獲取數據 */ public class DataProviderTest { /** * 數據源,是方法提供數據,返回必須是一個二維數組 * @DataProvider(name = "data") 經過該註解來標識這個爲數據源,name爲數據源的名稱。 * @return 返回一個二維數組 */ @DataProvider(name = "data") public Object[][] providerData() { Object[][] data = new Object[][] { {"zhangsan",12}, {"lisi",22}, {"wangwu",32} }; return data; } /** * 經過dataProvider來獲取數據,執行的次數會根據數據源提供數據的數量 * 例如上面的二維數組長度爲3,則該方法會執行三次。 * @param name * @param age */ @Test(dataProvider = "data") public void testDataProvider(String name, int age) { System.out.println("name=" + name + " age=" + age); } }
運行結果:
[TestNG] Running: C:\Users\Administrator\.IntelliJIdea2019.2\system\temp-testng-customsuite.xml name=zhangsan age=12 name=lisi age=22 name=wangwu age=32 =============================================== Default Suite Total tests run: 3, Failures: 0, Skips: 0 ===============================================
invocationCount:線程調用的次數,默認1次。
threadPoolSize:線程池大小,和 invocationCount 一塊兒使用,若是沒有定義 invocationCount ,定義了threadPoolSize,是沒有效果的。
@Test(invocationCount = 10,threadPoolSize = 3)
invocationCount 默認這個屬性的值是 1, 即只會執行一次,當重新賦值時,該方法就會執行屢次。
這裏就是,定義了三個線程,來執行這個方法10次。
示例:
package com.course.testng.multiThread; import org.testng.annotations.Test; public class MultiThreadOnAnnotion { @Test(invocationCount = 10,threadPoolSize = 3) public void test(){ System.out.println(1); System.out.printf("Thread Id : %s%n",Thread.currentThread().getId()); } }
運行結果:
[TestNG] Running: C:\Users\Administrator\.IntelliJIdea2019.2\system\temp-testng-customsuite.xml 1 1 1 Thread Id : 12 Thread Id : 11 1 Thread Id : 11 Thread Id : 13 1 Thread Id : 12 1 Thread Id : 12 1 Thread Id : 11 1 Thread Id : 12 1 Thread Id : 12 1 Thread Id : 13 =============================================== Default Suite Total tests run: 10, Failures: 0, Skips: 0 ===============================================
從輸出結果能夠看出,一共有三條線程在執行,一共執行了10次(輸出了10個1)
(1)建立測試類:MultiThreadOnXml.java
package com.ggf.testng.multithread; import org.testng.annotations.Test; /** * @Description: 使用配置文件來實現testng的多線程 * @Author: ggf * @Date: 2020/02/01 */ public class MultiThreadOnXml { @Test public void test1() { System.out.printf("Thread id: %s%n", Thread.currentThread().getId()); } @Test public void test2() { System.out.printf("Thread id: %s%n", Thread.currentThread().getId()); } @Test public void test3() { System.out.printf("Thread id: %s%n", Thread.currentThread().getId()); } }
(2)配置文件編寫
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" > <suite name="thread" parallel="methods" thread-count="3"> <!-- tests級別:不一樣的test tag下的用例能夠在不一樣的線程下執行 相同的test tag下的用例只能在同一個線程中去執行 classs級別:相同的class tag 下的用例在同一個線程中執行 不一樣的class tag 下的用例能夠在不一樣的線程中執行 methods級別:全部用例均可以在不一樣的線程下去執行 thread-count:表明了最大併發線程數 xml文件配置這種方式不能指定線程池,只有方法上才能夠指定線程池 --> <test name="test1"> <classes> <class name="com.ggf.testng.multithread.MultiThreadOnXml"/> </classes> </test> </suite>
(3) 運行結果
[TestNG] Running: D:\workspace\testwork\testNGDemo\src\main\resources\multithread.xml Thread id: 11 Thread id: 13 Thread id: 12 =============================================== thread Total tests run: 3, Failures: 0, Skips: 0 ===============================================
輸出結果能夠看出,有三條線程分別執行了不一樣的方法。
參考資料:
博客:
https://www.cnblogs.com/aland-1415/p/10475957.html
https://www.cnblogs.com/meitian/p/5221202.html
視頻教程:
https://coding.imooc.com/class/204.html