天天看點

testng使用詳解

一、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 -->
           
testng使用詳解

從這個結果顯示出注釋的作用位置。其中

@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 必選項,的名字,将出現在reports裡 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"
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"

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>

三部分組成

參數
test的名字,将出現在報告裡 name="testname" test的名字
是否按照Junit模式運作
控制台輸出的詳細内容等級,0-10級(0無,10最詳細),不在報告顯示
與suite的parallel一緻,預設false
标記是否執行這個test enabled="true"
是否按照排序執行,如果是true,将按照xml檔案中的順序去執行

[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

視訊教程:

https://coding.imooc.com/class/204.html