前言

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. Linux系统调优——系统整体运行状态排查(七)

    (1).vmstat vmstat命令是最常见的Linux/Unix监控工具,可以展现给定时间间隔的服务器的整体状态值,包括服务器的CPU使用率,MEM内存使用,VMSwap虚拟内存交换情况,IO读写 ...

  2. Linux系统调优——Memory内存(二)

    (1).查看Memory(内存)运行状态相关工具 1)free命令查看内存使用情况 [root@youxi1 ~]# free -m //-m选项,以MB为单位显示 total used free s ...

  3. 改进初学者的PID-手自动切换

    最近看到了Brett Beauregard发表的有关PID的系列文章,感觉对于理解PID算法很有帮助,于是将系列文章翻译过来!在自我提高的过程中,也希望对同道中人有所帮助.作者Brett Beaure ...

  4. kubectl exec 执行 容器命令

    格式如下: kubectl exec -it podName -c containerName -n namespace -- shell comand 1 创建目录 kubectl exec -it ...

  5. RabbitMQ官方教程四 Routing(GOLANG语言实现)

    在上一教程中,我们构建了一个简单的日志记录系统. 我们能够向许多消费者广播日志消息. 在本教程中,我们将向其中添加功能-我们将使仅订阅消息的子集成为可能. 例如,我们将只能将严重错误消息定向到日志文件 ...

  6. linux 下修改时间

    修改linux的时间可以使用date指令 date命令的功能是显示和设置系统日期和时间. 输入date 查看目前系统时间. 修改时间需要 date -功能字符 修改内容 命令中各选项的含义分别为: - ...

  7. 01. xadmin表单的自定义排版

    xadmin表单的自定义布局(重写 get_form_layout()) apps.courses.adminx.py class NewCoursesAdmin(object): list_disp ...

  8. CVE-2019-2725修复(删包)

    本来想试试打补丁,但是有些麻烦,而且oracle补丁黑名单的方式总不让人放心. 因此考虑直接删除相关的包. 该方式适用于xmldecoder漏洞系列,如CVE-2017-3506.CVE-2017-1 ...

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

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

  10. git实现码云的上传和下载

    上传步骤: 1.码云上新建一个项目 XXXX? ?(项目名) 2.本地创建一个文件夹E:/XXXX,然后使用git bash? ?? 3.cd 到本地文件夹中E:/XXXX? //如果是在创建的文件中 ...