java testng执行并行测试

转自:https://www.jianshu.com/p/4ba104a55df6

TestNG中实现多线程并行执行,可以通过几种方法

  1. testng.xml中配置
  2. @Test注解
  3. @DataProvider注解

testng.xml中配置

testng.xml中可以通过配置Suite、test标签的parallel、thread-count属性来实现

testng.xml中标签属性及含义
name:此套件的名称。这是一个强制性的属性。
parallel:由TestNG 运行不同的线程来运行此套件。
thread-count:使用的线程数,如果启用并行模式(忽略其他方式)

设置方法:

<suite name="test" parallel="tests" thread-count="5">
<suite name="test" parallel="classes" thread-count="5">
<suite name="test" parallel="methods" thread-count="5">

表示:最多起5个线程去同时执行不同的用例
它们的区别是:

  1. methods
    method 级别的多线程测试,每个方法都将采用独立的线程进行测试
  2. classes
    不同<class>标签下的用例可以在不同的线程执行,相同<class>标签下的用例只能在同一个线程中执行
  3. tests
    test级别的多线程测试,每个<test>标签下的所有方法将在同一个线程中执行,不同的<test>是在不同的线程来运行的

并行执行测试方法

由每一个独立的线程分别执行各自的测试方法,这种方式能够显著地减少测试执行时间,这是因为当有越多的测试方法被并行执行时,总体测试消耗时间将会越少。

public class ParallelMethodTest {

    @BeforeMethod
    public void beforeMethod(){
        long id = Thread.currentThread().getId();
        System.out.println("Before test-method. Thread id is: " + id);
    }

    @Test
    public void testMethodOne(){
        long id = Thread.currentThread().getId();
        System.out.println("Simple test-method One. Thread id is: " + id);
    }

    @Test
    public void testMethodTwo(){
        long id = Thread.currentThread().getId();
        System.out.println("Simple test-method One. Thread id is: " + id);
    }

    @AfterMethod
    public void afterMethod(){
        long id = Thread.currentThread().getId();
        System.out.println("After test-method. Thread id is: " + id);
    }
}

直接执行该类,如下图所示,可以看出两个方法都是同一个线程来执行。


 

我们可以在testng.xml文件中加入如下配置

<suite name="Suite" parallel="methods" thread-count="2">
    <test name="test">
        <classes>
            <class name="com.sell.test.ParallelMethodTest" />
        </classes>
    </test>
</suite>

用TestNG测试套件的方式来执行,执行结果如下图所示,可以看到两个测试方法执行的线程id是不同的,即实现了测试方法的并行执行:


 

并行执行测试类

同一个测试组件(test execution)中的各个测试类将会在独立的线程中并行地执行
ParallelClassesTest1.java

public class ParallelClassesTest1 {
    @BeforeClass
    public void beforeClass(){
        long id = Thread.currentThread().getId();
        System.out.println("Before test-class. Thread id is: " + id);
    }
    @Test
    public void testMethodOne(){
        long id = Thread.currentThread().getId();
        System.out.println("Simple test-method One. Thread id is: " + id);
    }
    @Test
    public void testMethodTwo(){
        long id = Thread.currentThread().getId();
        System.out.println("Simple test-method Two. Thread id is: " + id);
    }
    @AfterClass
    public void afterClass(){
        long id = Thread.currentThread().getId();
        System.out.println("After test-class. Thread id is: " + id);
    }
}

ParallelClassesTest2.java

public class ParallelClassesTest2 {
    @BeforeClass
    public void beforeClass(){
        long id = Thread.currentThread().getId();
        System.out.println("Before test-class. Thread id is: " + id);
    }
    @Test
    public void testMethodOne(){
        long id = Thread.currentThread().getId();
        System.out.println("Simple test-method One. Thread id is: " + id);
    }
    @Test
    public void testMethodTwo(){
        long id = Thread.currentThread().getId();
        System.out.println("Simple test-method Two. Thread id is: " + id);
    }
    @AfterClass
    public void afterClass(){
        long id = Thread.currentThread().getId();
        System.out.println("After test-class. Thread id is: " + id);
    }
}

在testng.xml添加配置如下:

<suite name="Suite" parallel="classes" thread-count="2">
    <test name="test">
        <classes>
            <class name="com.sell.test.ParallelClassesTest1" />
            <class name="com.sell.test.ParallelClassesTest2" />
        </classes>
    </test>
</suite>

以TestNG测试套件方式运行,运行结果如下,可以看出并行执行两个测试类:


 

并行执行同一测试套件内的各个测试组件

public class ParallelSuiteTest {
    String testName = "";

    @BeforeTest
    @Parameters("testName")
    public void beforeTest(String testName){
        this.testName = testName;
        long id = Thread.currentThread().getId();
        System.out.println("Before test " + testName + ". Thread id is: " + id);
    }

    @BeforeClass
    public void beforeClass() {
        long id = Thread.currentThread().getId();
        System.out.println("Before test-class " + testName + ". Thread id is: " + id);
    }

    @Test
    public void testMethodOne() {
        long id = Thread.currentThread().getId();
        System.out.println("Sample test-method " + testName + ". Thread id is: " + id);
    }

    @AfterClass
    public void afterClass() {
        long id = Thread.currentThread().getId();
        System.out.println("After test-method  " + testName + ". Thread id is: " + id);
    }

    @AfterTest
    public void afterTest() {
        long id = Thread.currentThread().getId();
        System.out.println("After test  " + testName + ". Thread id is: " + id);
    }
}

这里用到@Parameters参数化

执行结果如下图,可以看出两个测试组件是在两个独立线程中执行的:


 

@Test注解

TestNG提供了一种灵活的方式来配置需要在多线程环境下运行的测试方法:通过@Test注解的threadPoolSize等属性来实现多线程执行测试方法。当需要对某一个接口进行并发测试时,可以通过这种方法来实现。

    @Test(threadPoolSize = 3,invocationCount = 6,timeOut = 1000)

@Test的配置解释
@Test注解通过配置threadPoolSize这个属性来进入多线程模式
threadPoolSize被设为3,这就说明了该测试方法将会在三个不同的线程中同时执行
invocationCount配置的是该测试方法应被执行的总次数
timeOut配置的是每次执行该测试方法所耗费时间的阈值,超过阈值则测试失败

    @Test(dataProvider = "test2",threadPoolSize = 5,invocationCount = 10)

如果同时又DataProvider和threadPoolSize参数,则会根据DataProvider中的测试数据数量和invocationCount来确定最终的并发执行次数。
这里的线程池是用于起多个method,而每个method的测试数据由dp提供,如果这边dp里有3组数据,那么实际上10次执行,每次都会调3次接口,这个接口被调用的总次数是10*3=30次。threadPoolSize指定的5个线程中,每个线程单独去调method时,用到的dp如果也是支持并发执行的话,会创建一个新的线程池(dpThreadPool)来并发执行测试数据。具体实例可以通过下面的@DataProvider注解里的实例来进行试验,这里不再演示。

多线程执行测试方法

实例:

public class IndependentTest {

    @Test(threadPoolSize = 3,invocationCount = 6,timeOut = 1000)
    public void testMethod(){
        Long id = Thread.currentThread().getId();
        System.out.println("Test method executing on thread with id: " + id);
    }
}

执行结果如下,可以从打印出的日志中看出,该测试方法被执行了多次,而且它的执行次数跟invocationCount所指定的次数相同,且每次执行都是在不同的线程中完成的。当我们需要按照某一固定次数,在多线程环境下运行某些测试方法时,上述特性会很有帮助,因为它避免了我们把整个测试套件都并行执行多次的代价。


 

@DataProvider注解

在定义数据源的时候,可以通过设置parallel 属性来进行控制器是否并发执行测试,parallel 参数值默认为false,表示使用该数据源的测试方法不能并发执行,将其设置为true,表示使用该数据源的测试方法可以并发执行

并行执行测试方法实例

DataProviderParallelTest.java

public class DataProviderParallelTest {

    @Test(dataProvider = "test2")
    public void test2(String param1,String param2){
        long id = Thread.currentThread().getId();
        System.out.println(param1+"     "+param2 + " thread id:"+id);
    }


    @Test(dataProvider = "test1")
    public void test1(String param1,String param2){
        long id = Thread.currentThread().getId();
        System.out.println(param1+"     "+param2 + " thread id:"+id);
    }

    @DataProvider(name = "test2")
    public static Object[][] parallel2Test(){
        return new Object[][]{
                {"dataprovider test2 data1","dataprovider test2 data1"},
                {"dataprovider test2 data2","dataprovider test2 data2"}};
    }

    @DataProvider(name = "test1")
    public static Object[][] parallel1Test(){
        return new Object[][]{
                {"dataprovider test1 data1","dataprovider test1 data1"},
                {"dataprovider test1 data2","dataprovider test1 data2"}};
    }
}

先来看下不设置DataProvider的parallel参数时,执行情况,执行结果如下:


 

可以看出一个dp中的多组数据依然是顺序执行
这是如果设置DataProvider的parallel参数为true

 @DataProvider(name = "test2",parallel = true)
    public static Object[][] parallel2Test(){
        return new Object[][]{
                {"dataprovider test2 data1","dataprovider test2 data1"},
                {"dataprovider test2 data2","dataprovider test2 data2"}};
    }

    @DataProvider(name = "test1",parallel = true)
    public static Object[][] parallel1Test(){
        return new Object[][]{
                {"dataprovider test1 data1","dataprovider test1 data1"},
                {"dataprovider test1 data2","dataprovider test1 data2"}};
    }

次数执行结果如下:


 

可以看出,实现了dataprovider多组测试数据之间的并发,在实际使用过程中可以通过设置DataProvider的并发执行来缩短测试执行时间。
默认情况下,dp并行执行的线程池容量为10,如果要更改并发的数量,也可以在suite tag下指定参数data-provider-thread-count:

<suite name="Testng Parallel Test" parallel="methods" thread-count="5" data-provider-thread-count="20" >

小礼物走一走,来简书关注我



作者:威武不能屈
链接:https://www.jianshu.com/p/4ba104a55df6
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。
posted @ 2019-08-31 16:51  志不坚者智不达  阅读(1209)  评论(0编辑  收藏  举报