TestNG - 多线程测试

一、前言

  随着企业内部自动化资产的持续积累以及持续集成的推进,对自动化测试的运行速度要求越来越高,某些应用的自动化测试用例可能多达几千条,如何加速这些自动化用例的运行速度,让自动化落实到每一次版本变更和持续集成当中,是一个需要解决的问题。

二、TestNG 中的多线程使用姿势

1、测试方法中的并发

  有些时候,我们需要对一个测试用例,比如一个 http 接口,执行并发测试,即一个接口的反复调用,TestNG 中也提供了优雅的支持方式。

@Test(threadPoolSize = 5,invocationCount = 10)
    public void test1(){
        Assert.assertEquals(2,2);
        System.out.println("this is thread"+ Thread.currentThread().getId());
    }

  说明: threadPoolSize 表明用于调用该方法的线程池容量,该例就是同时起 5 个线程并行执行该方法;invocationCount 表示该方法总计需要被执行的次数。

该例子中 5 个线程同时执行,当总计执行次数达到 10 次时停止,执行结果如下:

 2、XML中的并发

  通常,在 TestNG 的执行中,测试的级别由上至下可以分为suite -> test -> class -> method,箭头的左边元素跟右边元素的关系是一对多的包含关系。

  这里的 test 指的是 testng.xml 中的 test tag,而不是测试类里的一个@Test。测试类里的一个@Test实际上对应这里的 method。所以我们在使用@BeforeSuite、@BeforeTest、@BeforeClass、@BeforeMethod这些标签的时候,它们的实际执行顺序也是按照这个级别来的。

1) test, class, method级别的并发,可以通过在 testng.xml 中的 suite tag 下设置,如:

<suite name="Testng Parallel Test" parallel="tests" thread-count="5">
<suite name="Testng Parallel Test" parallel="classes" thread-count="5">
<suite name="Testng Parallel Test" parallel="methods" thread-count="5">
说明:它们的共同点都是最多起 5 个线程去同时执行不同的用例。

 它们的区别如下:

  • tests 级别:不同 test tag 下的用例可以在不同的线程执行,相同 test tag 下的用例只能在同一个线程中执行。
  • classes 级别:不同 class tag 下的用例可以在不同的线程执行,相同 class tag 下的用例只能在同一个线程中执行。
  • methods 级别:所有用例都可以在不同的线程去执行。

  搞清楚并发的级别非常重要,可以帮我们合理地组织用例,比如将非线程安全的测试类或 group 统一放到一个 test 中,这样在并发的同时又可以保证这些类里的用例是单线程执行。也可以根据需要设定 class 级别的并发,让同一个测试类里的用例在同一个线程中执行。

2)实例演示

测试代码:TestMethods.java

package com.test.extent;
import org.testng.Assert;
import org.testng.Reporter;
import org.testng.annotations.Test;

public class TestMethods {

    @Test
    public void test1(){
        Assert.assertEquals(2,2);
        System.out.println("this is thread"+ Thread.currentThread().getId());
    }

    @Test
    public void test2(){
        Assert.assertEquals(1,1);
        System.out.println("this is thread"+ Thread.currentThread().getId());
    }

    @Test
    public void test3(){
        Assert.assertEquals("sss","sss");
        System.out.println("this is thread"+ Thread.currentThread().getId());
    }

}

xml设置:tests级别并发示例

<?xml version="1.0" encoding="UTF-8" ?>

<suite name="Suite1" parallel="tests" thread-count="2">
    <test name="测试用例1">
        <classes>
            <class name="com.test.extent.TestMethods"></class>
        </classes>
    </test>
    <test name="测试用例2">
        <classes>
            <class name="com.test.extent.TestMethods"></class>
        </classes>
    </test>
    <test name="测试用例3">
        <classes>
            <class name="com.test.extent.TestMethods"></class>
        </classes>
    </test>
</suite>

 说明:在当前测试规划的执行过程中,为每个测试用例(指的是xml中的<test>)的执行使用单独的线程(该测试用例中的测试方法共享一个线程),

最多并发2个线程,执行结果如下图:<test name="测试用例1">的3个方法的线程id均为16

xml设置:classes级别并发示例

<?xml version="1.0" encoding="UTF-8" ?>

<suite name="Suite1" parallel="classes" thread-count="2">
    <test name="测试用例1">
        <classes>
            <class name="com.test.extent.TestMethods"></class>
            <class name="com.test.extent.TestMethods2"></class>
        </classes>
    </test>
</suite>

 说明:在当前测试规划的执行过程中,为每个测试类(指的是xml中的<class>)的执行使用单独的线程(该测试类中的测试方法共享一个线程),最多并发2个线程。执行结果如下图:

xml设置:methods级别并发示例

<?xml version="1.0" encoding="UTF-8" ?>

<suite name="Suite1" parallel="methods" thread-count="2">
    <test name="test1">
        <classes>
            <class name="com.test.extent.TestMethods"></class>
        </classes>
    </test>
</suite>

  说明:在当前测试规划的执行过程中,为每个测试方法(指的是每个@Test)的执行使用单独的线程,最多并发2个线程,执行结果如下图:

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章