一、前言
随着企业内部自动化资产的持续积累以及持续集成的推进,对自动化测试的运行速度要求越来越高,某些应用的自动化测试用例可能多达几千条,如何加速这些自动化用例的运行速度,让自动化落实到每一次版本变更和持续集成当中,是一个需要解决的问题。
二、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个线程,执行结果如下图: