前言

TestNG有多种并发方式支持,方法的并发,class级的并发,test级的并发等;
根据实际应用可以灵活的配置和使用,下面分别对几种并发方法进行说明:

一、方法级并发

方法级并发即method级并发,此种并发方式需要将xml中的suite标签的parallel属性设置为methods并添加属性thread-count并设置其值,其会将所有的方法按照设定的并发数进行并发,譬如总共有4个测试用例,并发数设置为3,则会开三个线程,那么必然会有两个用例是在同一个线程内的,跟用例在哪个class内没关系,范例如下:
测试用例类一ThreadTest.java

package com.demo.test.testng;

import org.testng.annotations.Test;

public class ThreadTest {

	@Test()
public void test1()
{
long id = Thread.currentThread().getId();
System.out.println("test1-1 thread id:"+id);
} @Test
public void test2()
{
long id = Thread.currentThread().getId();
System.out.println("test1-2 thread id:"+id);
}
}

测试用例类二ThreadTest2

package com.demo.test.testng;

import org.testng.annotations.Test;

public class ThreadTest2 {

	@Test()
public void test1()
{
long id = Thread.currentThread().getId();
System.out.println("test2-1 thread id:"+id);
} @Test
public void test2()
{
long id = Thread.currentThread().getId();
System.out.println("test2-2 thread id:"+id);
}
}

xml设置并发数为3,并发类型为methods

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<suite name="threadSuite" parallel="methods" thread-count="3">
<test name="Test">
<classes>
<class name="com.demo.test.testng.ThreadTest"/>
<class name="com.demo.test.testng.ThreadTest2"/>
</classes>
</test> <!-- Test -->
</suite> <!-- Suite -->

执行结果如下:

[RemoteTestNG] detected TestNG version 6.10.0
[TestNG] Running:
D:\software\workspace\testng\src\main\java\com\demo\test\testCase\ThreadTestXml.xml test1-1 thread id:12
test2-1 thread id:14
test1-2 thread id:13
test2-2 thread id:13 ===============================================
threadSuite
Total tests run: 4, Failures: 0, Skips: 0
===============================================

如上图所示,确实是开了三个线程,且有两个相同线程号的用例并非同一个测试类;

二、class级并发

此并发方式需要将xml中的suite标签内的属性parallel属性设置为classes,且添加属性thread-count并设置其值即可实现class级别并发,其会一个class内的所有方法放在一个线程内,根据线程数设置和总的class数来分配线程,譬如如果设置线程数为3,而class数目为2,则会开两个线程来分别运行两个class,而如果设置线程数为3,且class数目为4则将会有两个class在一个线程内,如下为一个简单的范例:
两个用例类如下:
ThreadTest.java

package com.demo.test.testng;

import org.testng.annotations.Test;

public class ThreadTest {

	@Test()
public void test1()
{
long id = Thread.currentThread().getId();
System.out.println("test1-1 thread id:"+id);
} @Test
public void test2()
{
long id = Thread.currentThread().getId();
System.out.println("test1-2 thread id:"+id);
}
}

ThreadTest2.java

package com.demo.test.testng;

import org.testng.annotations.Test;

public class ThreadTest2 {

	@Test()
public void test1()
{
long id = Thread.currentThread().getId();
System.out.println("test2-1 thread id:"+id);
} @Test
public void test2()
{
long id = Thread.currentThread().getId();
System.out.println("test2-2 thread id:"+id);
}
}

测试xml如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<suite name="threadSuite" parallel="classes" thread-count="3" verbose="2">
<test name="Test">
<classes>
<class name="com.demo.test.testng.ThreadTest"/>
<class name="com.demo.test.testng.ThreadTest2"/>
</classes>
</test> <!-- Test -->
</suite> <!-- Suite -->

运行结果:

[RemoteTestNG] detected TestNG version 6.10.0
...
... TestNG 6.10 by Cédric Beust (cedric@beust.com)
... [TestNG] Running:
D:\software\workspace\testng\src\main\java\com\demo\test\testCase\ThreadTestXml.xml [TestRunner] Starting executor for test Test with time out:2147483647 milliseconds.
test2-1 thread id:13
test1-1 thread id:12
test2-2 thread id:13
test1-2 thread id:12
PASSED: test1
PASSED: test1
PASSED: test2
PASSED: test2 ===============================================
Test
Tests run: 4, Failures: 0, Skips: 0
===============================================

可以看到两个类分别开了一个线程,同一个类中的用例在同一个线程内,符合预期;
那么如果有一个suite下有多个test,这个并发设置会否将所有的test都计算在呢?来试一下,新添加一个测试用例Depend1.java

package com.demo.test.testng;

import org.testng.Assert;
import org.testng.annotations.Test; public class DependTest1 { @Test(groups= {"dependGroup1"})
public void dependTest1()
{
System.out.println("dependTest1");
} @Test(groups= {"dependGroup1"})
public void dependTest2()
{
System.out.println("dependTest2");
} @Test(groups="dependGroup2")
public void dependTest4()
{
System.out.println("dependTest4");
Assert.assertFalse(false);
}
}

修改xml为如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<suite name="threadSuite" parallel="classes" thread-count="2" verbose="2">
<test name="Test1">
<classes>
<class name="com.demo.test.testng.ThreadTest"/>
<class name="com.demo.test.testng.ThreadTest2"/>
</classes>
</test> <!-- Test -->
<test name="test2">
<classes>
<class name="com.demo.test.testng.DependTest1">
</class></classes>
</test>
</suite> <!-- Suite -->

再次运行结果如下:

[RemoteTestNG] detected TestNG version 6.10.0
...
... TestNG 6.10 by Cédric Beust (cedric@beust.com)
... [TestNG] Running:
D:\software\workspace\testng\src\main\java\com\demo\test\testCase\ThreadTestXml.xml [TestRunner] Starting executor for test Test1 with time out:2147483647 milliseconds.
test2-1 thread id:13
test1-1 thread id:12
test2-2 thread id:13
test1-2 thread id:12
PASSED: test1
PASSED: test1
PASSED: test2
PASSED: test2 ===============================================
Test1
Tests run: 4, Failures: 0, Skips: 0
=============================================== [TestRunner] Starting executor for test test2 with time out:2147483647 milliseconds.
dependTest1
dependTest2
dependTest4
PASSED: dependTest1
PASSED: dependTest2
PASSED: dependTest4 ===============================================
test2
Tests run: 3, Failures: 0, Skips: 0
=============================================== ===============================================
threadSuite
Total tests run: 7, Failures: 0, Skips: 0
===============================================

可以看到是先运行test1(内含两个测试类),开了两个线程,而后再运行test2(内含一个测试类),开了一个线程,而这两个test内的三个class是并没有放在一起运行的;
故这种并发设置是根据每个test标签生效的;

三、test级并发

test级并发为将xml中每个test标签下的用例放在一个线程内并根据并发数和tet数目开线程的并发方法,需要将xml中的suite标签内的属性parallel属性设置为tests,且添加属性thread-count并设置其值即可,譬如有一个suite下有两个test且并发数设置为2,那么就会开两个线程,每个线程都包含一个test,范例如下:
ThreadTest.java:

package com.demo.test.testng;

import org.testng.annotations.Test;

public class ThreadTest {

	@Test()
public void test1()
{
long id = Thread.currentThread().getId();
System.out.println("test1-1 thread id:"+id);
} @Test
public void test2()
{
long id = Thread.currentThread().getId();
System.out.println("test1-2 thread id:"+id);
}
}

ThreadTest2.java

package com.demo.test.testng;

import org.testng.annotations.Test;

public class ThreadTest2 {

	@Test()
public void test1()
{
long id = Thread.currentThread().getId();
System.out.println("test2-1 thread id:"+id);
} @Test
public void test2()
{
long id = Thread.currentThread().getId();
System.out.println("test2-2 thread id:"+id);
}
}

修改DependTest1.java:

package com.demo.test.testng;

import org.testng.Assert;
import org.testng.annotations.Test; public class DependTest1 { @Test(groups= {"dependGroup1"})
public void dependTest1()
{
long id = Thread.currentThread().getId();
System.out.println("dependTest1 id:"+id);
} @Test(groups= {"dependGroup1"})
public void dependTest2()
{
long id = Thread.currentThread().getId();
System.out.println("dependTest2 id:"+id);
} @Test(groups="dependGroup2")
public void dependTest4()
{
long id = Thread.currentThread().getId();
System.out.println("dependTest4 id:"+id);
Assert.assertFalse(false);
}
}

xml设置如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<suite name="threadSuite" parallel="tests" thread-count="2" verbose="2">
<test name="Test1">
<classes>
<class name="com.demo.test.testng.ThreadTest"/>
<class name="com.demo.test.testng.ThreadTest2"/>
</classes>
</test> <!-- Test -->
<test name="test2">
<classes>
<class name="com.demo.test.testng.DependTest1">
</class></classes>
</test>
</suite> <!-- Suite -->

运行结果:

[RemoteTestNG] detected TestNG version 6.10.0
...
... TestNG 6.10 by Cédric Beust (cedric@beust.com)
... [TestNG] Running:
D:\software\workspace\testng\src\main\java\com\demo\test\testCase\ThreadTestXml.xml [ThreadUtil] Starting executor timeOut:2147483647ms workers:2 threadPoolSize:2
dependTest1 id:13
test1-1 thread id:12
test1-2 thread id:12
dependTest2 id:13
test2-1 thread id:12
dependTest4 id:13
test2-2 thread id:12
PASSED: test1
PASSED: test2
PASSED: test1
PASSED: test2 ===============================================
Test1
Tests run: 4, Failures: 0, Skips: 0
=============================================== PASSED: dependTest1
PASSED: dependTest2
PASSED: dependTest4 ===============================================
test2
Tests run: 3, Failures: 0, Skips: 0
=============================================== ===============================================
threadSuite
Total tests run: 7, Failures: 0, Skips: 0
===============================================

可见两个test是开了两个线程运行的,且同一个test内的用例都在同一个线程内;

四、instances级并发

此并发方法与前面几种并发方法类似,只是需要修改parallelinstances即可,为一个实例一个并发,范例如下:

package com.demo.test.testng;

import java.util.ArrayList;
import java.util.List; import org.testng.annotations.Factory;
import org.testng.annotations.Test; public class FactoryTest { private String host;
private int port; public FactoryTest(String host, int port)
{
this.host=host;
this.port=port;
} @Test
public void login()
{
long id = Thread.currentThread().getId();
System.out.println("login, host:"+host+";port"+port+";id:"+id);
} @Test(dependsOnMethods="login")
public void logout()
{
long id = Thread.currentThread().getId();
System.out.println("logout, host:"+host+";port"+port+";id:"+id);
} @Factory
public static Object[] create()
{
List<FactoryTest> list = new ArrayList<FactoryTest>();
list.add(new FactoryTest("10.10.10.1", 8080));
list.add(new FactoryTest("10.10.10.2", 8080));
return list.toArray();
}
}

xml如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<suite name="threadSuite" parallel="instances" thread-count="4" verbose="2">
<test name="Test1">
<classes>
<class name="com.demo.test.testng.FactoryTest" />
</classes>
</test>
</suite> <!-- Suite -->

运行结果如下:

[RemoteTestNG] detected TestNG version 6.10.0
...
... TestNG 6.10 by Cédric Beust (cedric@beust.com)
... [TestNG] Running:
D:\software\workspace\testng\src\main\java\com\demo\test\testCase\ThreadTestXml.xml [TestRunner] Starting executor for test Test1 with time out:2147483647 milliseconds.
login, host:10.10.10.1;port8080;id:12
login, host:10.10.10.2;port8080;id:13
logout, host:10.10.10.1;port8080;id:14
logout, host:10.10.10.2;port8080;id:15
PASSED: login
PASSED: login
PASSED: logout
PASSED: logout ===============================================
Test1
Tests run: 4, Failures: 0, Skips: 0
=============================================== ===============================================
threadSuite
Total tests run: 4, Failures: 0, Skips: 0
===============================================

如上log可知,两个用例,两组参数,共四条用例开了四个线程,每个用例都是一个实例;
如果是没有@Factory注解的普通用例,则没效果。

五、测试用例级并发

此级并发可以直接在用例内设置,如下为一个范例:

package com.demo.test.testng;

import org.testng.annotations.Test;

public class ThreadTest {

	@Test(threadPoolSize = 3, invocationCount = 6, timeOut = 1000)
public void test1()
{
long id = Thread.currentThread().getId();
System.out.println("test1-1 thread id:"+id);
} @Test
public void test2()
{
long id = Thread.currentThread().getId();
System.out.println("test1-2 thread id:"+id);
}
}

如上图代码所示,test1设置线程数为3,调用次数为6,超时时间为1000ms,运行结果如下:

[RemoteTestNG] detected TestNG version 6.10.0
[TestNG] Running:
C:\Users\dufei\AppData\Local\Temp\testng-eclipse--1263110808\testng-customsuite.xml [ThreadUtil] Starting executor timeOut:1000ms workers:6 threadPoolSize:3
test1-1 thread id:13
test1-1 thread id:14
test1-1 thread id:12
test1-1 thread id:14
test1-1 thread id:13
test1-1 thread id:12
test1-2 thread id:1
PASSED: test1
PASSED: test1
PASSED: test1
PASSED: test1
PASSED: test1
PASSED: test1
PASSED: test2 ===============================================
Default test
Tests run: 7, Failures: 0, Skips: 0
=============================================== ===============================================
Default suite
Total tests run: 7, Failures: 0, Skips: 0
=============================================== [TestNG] Time taken by org.uncommons.reportng.HTMLReporter@1d371b2d: 48 ms

如上所示,test1为三个线程,调用六次,超时为1000ms,符合预期;

TestNG并发执行用例详解和范例的更多相关文章

  1. C++11 并发指南四(<future> 详解二 std::packaged_task 介绍)

    上一讲<C++11 并发指南四(<future> 详解一 std::promise 介绍)>主要介绍了 <future> 头文件中的 std::promise 类, ...

  2. C++11 并发指南四(<future> 详解三 std::future & std::shared_future)

    上一讲<C++11 并发指南四(<future> 详解二 std::packaged_task 介绍)>主要介绍了 <future> 头文件中的 std::pack ...

  3. C++11 并发指南四(<future> 详解三 std::future & std::shared_future)(转)

    上一讲<C++11 并发指南四(<future> 详解二 std::packaged_task 介绍)>主要介绍了 <future> 头文件中的 std::pack ...

  4. 《手把手教你》系列基础篇(七十五)-java+ selenium自动化测试-框架设计基础-TestNG实现DDT - 中篇(详解教程)

    1.简介 上一篇中介绍了DataProvider如何传递参数,以及和一些其他方法结合传递参数,今天宏哥接着把剩下的一些常用的也做一下简单的介绍和分享. 2.项目实战1 @DataProvider + ...

  5. MySQL 执行计划explain详解

    MySQL 执行计划explain详解 2015-08-10 13:56:27 分类: MySQL explain命令是查看查询优化器如何决定执行查询的主要方法.这个功能有局限性,并不总会说出真相,但 ...

  6. 批量执行工具PSSH详解

    批量执行工具PSSH详解 pssh是一个python编写可以在多台服务器上执行命令的工具,同时支持拷贝文件,是同类工具中很出色的,使用必须在各个服务器上配置好密钥认证访问. 安装pssh包 yum 安 ...

  7. 《手把手教你》系列基础篇(七十六)-java+ selenium自动化测试-框架设计基础-TestNG实现DDT - 下篇(详解教程)

    1.简介 今天这一篇宏哥主要是结合实际工作中将遇到的测试场景和前边两篇学习的知识结合起来给大家讲解和分享一下,希望以后大家在以后遇到其他的测试场景也可以将自己的所学的知识应用到测试场景中. 2.测试场 ...

  8. SQL Server 执行计划操作符详解(3)——计算标量(Compute Scalar)

    接上文:SQL Server 执行计划操作符详解(2)--串联(Concatenation ) 前言: 前面两篇文章介绍了关于串联(Concatenation)和断言(Assert)操作符,本文介绍第 ...

  9. SQL Server 执行计划操作符详解(2)——串联(Concatenation )

    本文接上文:SQL Server 执行计划操作符详解(1)--断言(Assert) 前言: 根据计划,本文开始讲述另外一个操作符串联(Concatenation),读者可以根据这个词(中英文均可)先幻 ...

随机推荐

  1. 123457123456#1#----com.ppGame.BaoBaoiMiYu35--前拼后广--miyu_pp

    com.ppGame.BaoBaoiMiYu35--前拼后广--miyu_pp

  2. 基于Python的WEB接口开发与自动化测试 pdf(内含书签)

    基于Python的WEB接口开发与自动化测试 目录 目 录O V目 录章 Python 学习必知 ................................................... ...

  3. Text Prompted Remote Speaker Authentication : Joint Speech and Speaker Recognition/Verification System :: Major Project ::: Introduction

    转载自:http://ganeshtiwaridotcomdotnp.blogspot.com/2010/12/text-prompted-remote-speaker.html Biometrics ...

  4. python 求交集、并集、差集

    需要用到set类型 交集,两种方法 retA = [i for i in listA if i in listB] retB = setA.intersection(setB) 并集 retC = s ...

  5. [转]gcc的__builtin_函数介绍

    链接地址:https://blog.csdn.net/jasonchen_gbd/article/details/44948523

  6. SPSS 2019年10月24日 今日学习总结

    2019年10月24日今日课上内容1.SPSS掌握基于键值的一对多合并2.掌握重构数据3.掌握汇总功能 内容: 1.基于键值的一对多合并 合并文件 添加变量 合并方法:基于键值的一对多合并 变量 2. ...

  7. 个人PC电脑 关闭网卡自启

    前言: 今早我打开我的电脑,惊呆了.出现了以下字样: This Product is covered by one or more of the following patents ... 看了BIO ...

  8. Use Hexo to Build My Gitee Blog

      之前有自己建站托管自己的博客系统, 后来因为流量实在太少, 服务器又要每个月出钱, 然后就把她关了, 然是拥有自己的网站的心一直没有退去啊, 然后之前有接触到别人用GitHub托管静态网页的玩法, ...

  9. [bzoj3420]Poi2013 Triumphal arch_树形dp_二分

    Triumphal arch 题目链接:https://lydsy.com/JudgeOnline/problem.php?id=3420 数据范围:略. 题解: 首先,发现$ k $具有单调性,我们 ...

  10. 有助提升编程的几个Python 技巧

    一行代码定义List 定义某种列表时,写For 循环过于麻烦,幸运的是,Python有一种内置的方法可以在一行代码中解决这个问题. 下面是使用For循环创建列表和用一行代码创建列表的对比. x = [ ...