一、testng 介紹
TestNG
是一個測試框架,其靈感來自 JUnit
和 NUnit
,但同時引入了一些新的功能,使其功能更強大,使用更方便。
TestNG
設計涵蓋所有類型的測試:單元,功能,端到端,集成等,它需要 JDK5
或更高的 JDK
版本。
詳細使用說明請參考官方鏈接: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 類
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)測試結果
[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注解及常用屬性
凡是在類方法中添加了 @Test
注解的就是我們需要測試的方法
1、enable 測試方法是否執行
默認是 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
===============================================
2、預期異常expectedExeption
@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
===============================================
3、依賴方法dependsOnMethods
在被依賴的方法運行完成之后運行當前方法,如果依賴方法測試不通過,那么當前方法也不會繼續運行了;依賴的方法可以有多個;
例:@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 ...");
}
}
4、分組groups
-
把在一個
<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
===============================================
5、超時屬性timeOut
@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
===============================================
6、屬性總結
屬性名 | 描述 |
---|---|
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,則忽略此屬性 |
三、testng常用注解
注解 | 描述 |
---|---|
@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,就循環執行多少次)。
四、testng.xml 配置文件詳解
1、配置文件結構(較詳細):
<?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>
2、配置文件標簽說明
[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>
五、testng 中方法參數傳遞
1、使用 @Parameters 注解從測試配置 xml 文件獲取參數
(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
===============================================
2、使用@DataProvider傳送參數,@DataProvider可以傳遞一些比較復雜的參數
示例:
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
===============================================
六、testng 多線程測試
1、使用注解實現多線程測試
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)
2、使用 xml 配置文件實現多線程測試
(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
視頻教程: