一、并行性和超时

您可以指示TestNG以各种方式在单独的线程中运行测试。

可以通过在suite标签中使用 parallel 属性来让测试方法运行在不同的线程中。这个属性可以带有如下这样的值:

二、并行套件(suites)

如果您正在运行多个套件文件(例如“ java org.testng.TestNG testng1.xml testng2.xml”),并且希望每个套件在单独的线程中运行,则这个很有用。您可以使用以下命令行标志来指定线程池的大小:

java org.testng.TestNG -suitethreadpoolsize 3 testng1.xml testng2.xml testng3.xml

相应的ant任务名称为suitethreadpoolsize

三、并行测试,类和方法

在并行于<suite>标记属性可以取下列值之一:

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

parallel =“ methods”:TestNG将在单独的线程中运行所有测试方法。依赖方法也将在单独的线程中运行,但是它们将遵循您指定的顺序。
parallel =“ tests”:TestNG将在同一线程中的同一<test>标记中运行所有方法,但是每个<test>标记将位于单独的线程中。这样,您就可以将所有不是线程安全的类归入同一个<test>中,并确保它们都将在同一线程中运行,同时利用TestNG使用尽可能多的线程来运行测试。
平行=“类”:TestNG的将运行在相同的线程相同的类的所有方法,但每个类将在单独的线程中运行。
parallel =“ instances”:TestNG将在同一线程中的同一实例中运行所有方法,但是在两个不同实例中的两个方法将在不同线程中运行。
此外,属性 thread-count允许您指定应为此执行分配多少个线程。
注意:@Test属性timeOut在并行和非并行模式下均可工作。
您还可以指定从不同的线程调用@Test方法。您可以使用属性threadPoolSize来实现以下结果:

@Test(threadPoolSize = 3, invocationCount = 10,  timeOut = 10000)
public void testServer() {

在此示例中,将从三个不同的线程调用函数testServer十次。此外,十秒的超时保证没有任何线程将永远在该线程上阻塞。

四、重新运行失败的测试

每当套件中的测试失败时,TestNG都会在输出目录中创建一个名为testng-failed.xml的文件。此XML文件包含必要的信息,以仅重新运行失败的这些方法,从而使您可以快速重现失败,而不必运行整个测试。因此,典型的会话如下所示:

java -classpath testng.jar;%CLASSPATH% org.testng.TestNG -d test-outputs testng.xml
java -classpath testng.jar;%CLASSPATH% org.testng.TestNG -d test-outputs test-outputs\testng-failed.xml

请注意,testng-failed.xml将包含所有必需的依赖方法,因此可以确保您运行失败的方法而不会出现任何SKIP失败。

有时,您可能希望TestNG在测试失败时自动重试。在这种情况下,您可以使用重试分析器。当您将重试分析器绑定到测试时,TestNG会自动调用重试分析器,以确定TestNG是否可以再次重试测试用例,以查看是否刚刚通过的测试现在通过。这是使用重试分析器的方法:

  1. 构建接口org.testng.IRetryAnalyzer的实现
  2. 将此实现绑定到@Test注释,例如@Test(retryAnalyzer = LocalRetry.class)

以下是重试分析器的示例实现,该示例最多重试一次测试三次。

import org.testng.IRetryAnalyzer;
import org.testng.ITestResult; /**
* @author 北京-宏哥
*
* Java自动化测试框架-08 - TestNG之 TestNG之并行性和超时篇
*
* 2019年11月7日
*/ public class MyRetry implements IRetryAnalyzer { private int retryCount = 0;
private static final int maxRetryCount = 3; @Override
public boolean retry(ITestResult result) {
if (retryCount < maxRetryCount) {
retryCount++;
return true;
}
return false;
}
}
import org.testng.Assert;
import org.testng.annotations.Test; /**
* @author 北京-宏哥
*
* Java自动化测试框架-08 - TestNG之 TestNG之并行性和超时篇
*
* 2019年11月7日
*/ public class TestclassSample { @Test(retryAnalyzer = MyRetry.class)
public void test2() {
Assert.fail();
}
}

五、JUnit测试

TestNG可以运行JUnit 3和JUnit 4测试。所有你需要做的就是把JUnit的jar文件在类路径中,在指定JUnit测试类,testng.classNames 属性和设置testng.junit属性设置为true:

<test name="Test1" junit="true">
<classes>
<!-- ... -->

在这种情况下,TestNG的行为类似于JUnit,这取决于在类路径上找到的JUnit版本:

  • JUnit 3:

    • 您的课程中所有以test *开头的方法都将运行
    • 如果您的测试类上有一个方法setUp(),它将在每个测试方法之前调用
    • 如果您的测试类上有一个方法tearDown(),它将在每个测试方法之后被调用
    • 如果您的测试类包含方法suite(),则将调用此方法返回的所有测试
  • JUnit 4:
    • TestNG将使用org.junit.runner.JUnitCore运行程序运行测试

六、以编程的方式运行testng

您可以从自己的程序中轻松调用TestNG:

TestListenerAdapter tla = new TestListenerAdapter();
TestNG testng = new TestNG();
testng.setTestClasses(new Class[] { Run2.class });
testng.addListener(tla);
testng.run();

本示例创建一个TestNG对象并运行测试类Run2。它还添加了一个TestListener。您可以使用适配器类org.testng.TestListenerAdapter或自己实现org.testng.ITestListener。此接口包含各种回调方法,可让您跟踪测试的开始时间,成功时间,失败时间等。

同样,您可以在testng.xml文件上调用TestNG,也可以自己创建一个虚拟的testng.xml文件。为此,您可以使用发现包org.testng.xml的类: XmlClassXmlTest等。这些类中的每一个都对应于它们的XML标记对应物。

例如,假设您要创建以下虚拟文件:

<suite name="TmpSuite" >
<test name="TmpTest" >
<classes>
<class name="test.failures.Child" />
<classes>
</test>
</suite>

您将使用以下代码:

XmlSuite suite = new XmlSuite();
suite.setName("TmpSuite"); XmlTest test = new XmlTest(suite);
test.setName("TmpTest");
List<XmlClass> classes = new ArrayList<XmlClass>();
classes.add(new XmlClass("test.failures.Child"));
test.setXmlClasses(classes) ;

然后,您可以将此XmlSuite传递给TestNG:

List<XmlSuite> suites = new ArrayList<XmlSuite>();
suites.add(suite);
TestNG tng = new TestNG();
tng.setXmlSuites(suites);
tng.run();

有兴趣的:请参阅JavaDocs了解整个API。

七、BeanShell和高级组选择

如果testng.xml中的<include><exclude>标记不足以满足您的需要,则可以使用BeanShell表达式来确定是否应在测试运行中包括某种测试方法。您可以在<test>标记下指定此表达式:

<test name="BeanShell test">
<method-selectors>
<method-selector>
<script language="beanshell"><![CDATA[
groups.containsKey("test1")
]]></script>
</method-selector>
</method-selectors>
<!-- ... -->

<SCRIPT>标记中发现的testng.xml,TestNG的将忽略随后的<包括><排除>在当前组和方法的<试验>标记:你的BeanShell的表达将是决定是否一个测试方法的唯一方式是否包含在内。

以下是有关BeanShell脚本的其他信息:

它必须返回一个布尔值。除了此约束之外,还允许使用任何有效的BeanShell代码(例如,您可能希望在工作日返回true,在周末返回false,这将允许您根据日期以不同的方式运行测试)
为了方便起见,TestNG定义了以下变量:
1、java.lang.reflect.Method method:当前的测试方法。
2、org.testng.ITestNGMethod testngMethod:当前测试方法的描述。
3、java.util.Map <String,String> groups:当前测试方法所属的组的映射。
您可能希望用CDATA声明包围表达式(如上所示),以避免冗长的保留XML字符引用。

八、Annotation Transformers

TestNG允许您在运行时修改所有注释的内容。如果源代码中的注释大多数时候都是正确的,则这特别有用,但是在某些情况下,您想覆盖它们的值。

为了实现此目的,您需要使用注释转换器。

Annotation Transformer是一个实现以下接口的类:

public interface IAnnotationTransformer {

  /**
* This method will be invoked by TestNG to give you a chance
* to modify a TestNG annotation read from your test classes.
* You can change the values you need by calling any of the
* setters on the ITest interface.
*
* Note that only one of the three parameters testClass,
* testConstructor and testMethod will be non-null.
*
* @param annotation The annotation that was read from your
* test class.
* @param testClass If the annotation was found on a class, this
* parameter represents this class (null otherwise).
* @param testConstructor If the annotation was found on a constructor,
* this parameter represents this constructor (null otherwise).
* @param testMethod If the annotation was found on a method,
* this parameter represents this method (null otherwise).
*/
public void transform(ITest annotation, Class testClass,
Constructor testConstructor, Method testMethod);
}

像所有其他TestNG侦听器一样,您可以在命令行或使用ant来指定此类:

java org.testng.TestNG -listener MyTransformer testng.xml
 

或以编程方式:

TestNG tng = new TestNG();
tng.setAnnotationTransformer(new MyTransformer());
// ...

调用 方法transform()时,可以在TestNG继续进行之前,调用ITest测试参数上的任何设置方法来更改其值。

例如,这是您如何重写属性invocationCount的方法,但仅在其中一个测试类的测试方法invoke()上:

/**
* @author 北京-宏哥
*
* Java自动化测试框架-08 - TestNG之 TestNG之并行性和超时篇
*
* 2019年11月7日
*/
public class MyTransformer implements IAnnotationTransformer {
public void transform(ITest annotation, Class testClass,
Constructor testConstructor, Method testMethod)
{
if ("invoke".equals(testMethod.getName())) {
annotation.setInvocationCount(5);
}
}
}

IAnnotationTransformer仅允许您修改@Test注释。如果需要修改另一个TestNG批注(配置批注@Factory@DataProvider),请使用IAnnotationTransformer2

九、方法拦截器

一旦TestNG 计算好了测试方法会以怎样的顺序调用,那么这些方法就会分为两组:

1.按照顺序运行的方法。这里所有的方法都有相关的依赖,并且所有这些方法按照特定顺序运行。

2.不定顺序运行的方法。这里的方法不属于第一个类别。方法的运行顺序是随机的,下一个说不准是什么(尽管如此,默认情况下TestNG会尝试通过类来组织方法)。

为了能够让你更好的控制第二种类别,TestNG定义如下接口:

方法中叫做methods的那个列表参数包含了所有以不定序运行的方法。你的 intercept 方法也要返回一个 IMethodInstance列表,它可能是下面情况之一:

1.内容与参数中接收的一致,但是顺序不同

2.一组 IMethodInstance 对象

3.更大的一组 IMethodInstance对象

一旦你定义了拦截器,就把它传递个TestNG,用下面的方式:

java -classpath "testng-jdk15.jar:test/build" org.testng.TestNG -listener test.methodinterceptors.NullMethodInterceptor
-testclass test.methodinterceptors.FooTest

有关等效的ant语法,请参见ant文档中listeners属性。

例如,这是一个方法拦截器,它将对方法进行重新排序,以便始终首先运行属于“快速”组的测试方法:

/**
* @author 北京-宏哥
*
* Java自动化测试框架-08 - TestNG之 TestNG之并行性和超时篇
*
* 2019年11月7日
*/
public List<IMethodInstance> intercept(List<IMethodInstance> methods, ITestContext context) {
List<IMethodInstance> result = new ArrayList<IMethodInstance>();
for (IMethodInstance m : methods) {
Test test = m.getMethod().getConstructorOrMethod().getAnnotation(Test.class);
Set<String> groups = new HashSet<String>();
for (String group : test.groups()) {
groups.add(group);
}
if (groups.contains("fast")) {
result.add(0, m);
}
else {
result.add(m);
}
}
return result;
}

十、TestNG侦听器

有几个接口可让您修改TestNG的行为。这些接口广泛地称为“ TestNG侦听器”。以下是一些听众:

当实现这些接口之一时,可以通过以下两种方式之一让TestNG知道它:

十一、使用的testng.xml或Java的指定监听器

这是在testng.xml文件中定义侦听器的方法:

<suite>

  <listeners>
<listener class-name="com.example.MyListener" />
<listener class-name="com.example.MyMethodInterceptor" />
</listeners> ...

或者,如果您更喜欢用Java定义这些侦听器,则:

@Listeners({ com.example.MyListener.class, com.example.MyMethodInterceptor.class })
public class MyTest {
// ...
}

@Listeners注释可以包含任何扩展类org.testng.ITestNGListener 除了 IAnnotationTransformerIAnnotationTransformer2。原因是这些侦听器需要在过程的早期就知道,以便TestNG可以使用它们来重写您的注释,因此您需要在testng.xml文件中指定这些侦听器。

请注意,@ Listeners批注将应用于您的整个套件文件,就像您在testng.xml文件中指定的一样。如果要限制其范围(例如,仅在当前类上运行),则侦听器中的代码可以首先检查将要运行的测试方法,然后决定要做什么。这是可以完成的。

1、首先定义一个新的自定义注释,可用于指定此限制:

@Retention(RetentionPolicy.RUNTIME)
@Target ({ElementType.TYPE})
public @interface DisableListener {}

2、在常规侦听器中添加如下所示的编辑检查:

public void beforeInvocation(IInvokedMethod iInvokedMethod, ITestResult iTestResult) {
ConstructorOrMethod consOrMethod =iInvokedMethod.getTestMethod().getConstructorOrMethod();
DisableListener disable = consOrMethod.getMethod().getDeclaringClass().getAnnotation(DisableListener.class);
if (disable != null) {
return;
}
// else resume your normal operations
}

3、注释测试类,其中不调用侦听器:

@DisableListener
@Listeners({ com.example.MyListener.class, com.example.MyMethodInterceptor.class })
public class MyTest {
// ...
}

十二、使用的ServiceLoader指定侦听器

最后,JDK提供了一种非常优雅的机制,可以通过ServiceLoader类在类路径上指定接口的实现。
使用ServiceLoader,您要做的就是创建一个包含侦听器和一些配置文件的jar文件,在运行TestNG时将该jar文件放在类路径中,TestNG会自动找到它们。

这是其工作方式的具体示例。

让我们从创建一个监听器开始(任何TestNG监听器都可以工作):

package test.tmp;

public class TmpSuiteListener implements ISuiteListener {
@Override
public void onFinish(ISuite suite) {
System.out.println("Finishing");
} @Override
public void onStart(ISuite suite) {
System.out.println("Starting");
}
}

编译该文件,然后在META-INF / services / org.testng.ITestNGListener位置创建一个文件,该文件将命名您想要此接口的实现。
您应该以以下目录结构结束,只有两个文件:

$ tree
|____META-INF
| |____services
| | |____org.testng.ITestNGListener
|____test
| |____tmp
| | |____TmpSuiteListener.class $ cat META-INF/services/org.testng.ITestNGListener
test.tmp.TmpSuiteListener

创建此目录的jar:

$ jar cvf ../sl.jar .
added manifest
ignoring entry META-INF/
adding: META-INF/services/(in = 0) (out= 0)(stored 0%)
adding: META-INF/services/org.testng.ITestNGListener(in = 26) (out= 28)(deflated -7%)
adding: test/(in = 0) (out= 0)(stored 0%)
adding: test/tmp/(in = 0) (out= 0)(stored 0%)
adding: test/tmp/TmpSuiteListener.class(in = 849) (out= 470)(deflated 44%)

接下来,在调用TestNG时,将此jar文件放在类路径中:

$ java -classpath sl.jar:testng.jar org.testng.TestNG testng-single.yaml
Starting
f2 11 2
PASSED: f2("2")
Finishing

通过此机制,您只需将jar文件添加到类路径即可将相同的一组侦听器应用于整个组织,而不是要求每个开发人员都记住在其testng.xml文件中指定这些侦听器。

十三、小结

  好了,今天关于TestNG之并行性和超时,就分享到这里。

Java自动化测试框架-08 - TestNG之并行性和超时篇 (详细教程)的更多相关文章

  1. Java自动化测试框架-01 - TestNG之入门篇 - 大佬的鸡肋,菜鸟的盛宴(详细教程)

    TestNG是什么? TestNG按照官方的定义: TestNG是一个测试框架,其灵感来自JUnit和NUnit,但引入了一些新的功能,使其功能更强大,使用更方便. TestNG是一个开源自动化测试框 ...

  2. Java自动化测试框架-02 - TestNG之理论实践 - 纸上得来终觉浅,绝知此事要躬行(详细教程)

    理论 TestNG,即Testing, NextGeneration,下一代测试技术,是一套根据JUnit 和NUnit思想而构建的利用注释来强化测试功能的一个测试框架,即可以用来做单元测试,也可以用 ...

  3. Java自动化测试框架-03 - TestNG之Test Group篇 - 我们一起组团打怪升级(详细教程)

    简介 其实这篇文章的group宏哥在上一篇中就提到过,但是就是举例一笔带过的,因此今天专门有一篇文章来讲解Group的相关知识.希望大家茅塞顿开 ,有着更进一步认识和了解测试组. 一.Test Gro ...

  4. Java自动化测试框架-04 - TestNG之Test Method篇 - 道法自然,法力无边(详细教程)

    简介 按照上一篇的计划,这一篇给小伙伴们分享一下测试方法. 一.设置参数 测试方法是可以带有参数的.每个测试方法都可以带有任意数量的参数,并且可以通过使用TestNG的@Parameters向方法传递 ...

  5. Java自动化测试框架-07 - TestNG之Factory篇 - 欢快畅游梦幻工厂(详细教程)

    简介 最近忙着装修博客园,没时间更新文章,今天终于抽出时间把上次写的一半的文章给写完了,新的博客园风格,希望大家喜欢.今天继续介绍testng的相关知识--工厂. 工厂允许你动态的创建测试.例如,假设 ...

  6. Java自动化测试框架-09 - TestNG之依赖注入篇 (详细教程)

    1.-依赖注入 TestNG支持两种不同类型的依赖项注入:本机(由TestNG本身执行)和外部(由诸如Guice的依赖项注入框架执行). 1.1-本机依赖项注入 TestNG允许您在方法中声明其他参数 ...

  7. Java自动化测试框架-10 - TestNG之测试结果篇

    1.-测试结果 1.1-成功,失败和断言 测试被认为是成功的,如果它不引发任何异常完成,还是它扔的预期异常(请参阅文档expectedExceptions属性上找到的@Test注释). 您的测试方法通 ...

  8. Java自动化测试框架-11 - TestNG之annotation与并发测试篇 (详细教程)

    1.简介 TestNG中用到的annotation的快速预览及其属性. 2.TestNG基本注解(注释) 注解 描述 @BeforeSuite 注解的方法只运行一次,在当前suite所有测试执行之前执 ...

  9. Java自动化测试框架-02 - TestNG之理论到实践

    TestNG,即Testing, NextGeneration,下一代测试技术,是一套根据JUnit 和NUnit思想而构建的利用注释来强化测试功能的一个测试框架,即可以用来做单元测试,也可以用来做集 ...

随机推荐

  1. locate,find

    locate:非实时查找,模糊匹配,查找是根据全系统文件数据库进行的,可以使用updatedb命令来手动生成数据库 find:实时查找,精确匹配,支持众多查找标准,遍历指定目录中的所有文件完成查找,速 ...

  2. 手把手教你如何在Windows下allure与jenkins的集成生成让你一见钟情的测试报告 - 03(非常详细,非常实用)

    简介 好了,国庆假期结束,开始搬砖.为什么要把allure和jenkins集成了?原因是集成以后,我们就可以直接查看allure的结果,不需要重复输入命令.重复使用浏览器打开文件来查看allure的结 ...

  3. FFmpeg(二) 解封装相关函数理解

    一.解封装基本流程 ①av_register_All()////初始化解封装,注册解析和封装的格式. ②avformat_netword_init()//初始化网络,解析rtsp协议 ③avforma ...

  4. iOS性能优化-异步绘制

    参考地址:https://blog.ibireme.com/2015/11/12/smooth_user_interfaces_for_ios/ 很久以前就看过这篇文章,但是也只是看过就过了,没有去整 ...

  5. Nebula 架构剖析系列(零)图数据库的整体架构设计

    Nebula Graph 是一个高性能的分布式开源图数据库,本文为大家介绍 Nebula Graph 的整体架构. 一个完整的 Nebula 部署集群包含三个服务,即  Query Service,S ...

  6. JDBC访问数据库的基本步骤

    加载驱动 通过DriverManager对象获取连接对象Connection 通过连接对象获取会话 通过会话进行数据的增删改查,封装对象 关闭资源

  7. PCIE DMA实现

    基于Spartan-6, Virtex-5/Virtex-6/Virtex-7/7 Series FPGA PCI Express Block Endpoint模块设计PCI Express Endp ...

  8. python编程基础之二十四

    函数: def 函数名([参数1],[参数2],[参数3], ... ,[参数n]): 函数体代码 函数名命名规则:同标识符命名相同,但是多了一点,不要和系统函数重名,其实所有命名都是一样只要符合标识 ...

  9. uniapp 与C# 加解密

    1 uni-app操作 (1) 打开HBuilderX的视图->显示终端 cd 切换到你项目的根目录 执行命令 npm install crypto-js 安装成功后你的项目根目录会生成node ...

  10. 终端 10X 工作法(一)

    目录 1. Terminal 2. Grep 3. Sed 4. Awk 5. Xargs 6. Find 在 github 上面有一个 700 多人 star 的 repo 叫做 Bash-Onel ...