当前位置: 首页 > 知识库问答 >
问题:

是否可以在testng中为测试类而不是单个方法创建套件级别的超时?

周威
2023-03-14

我正在研究testng中的一个问题。我想知道是否有办法在测试类级别指定超时,而不是单个方法。我知道套件xml级别的“超时”,但这适用于每个测试类中的每个测试方法。

我真的希望能够指定一个适用于xml中每个类的超时,这样我们就可以研究如何改进这些类。

共有2个答案

祁永嘉
2023-03-14

这是不支持的开箱即用。但是TestNG确实为您提供了一些功能,您应该能够使用这些功能自行构建它,而无需付出多少努力。[我使用TestNG7.0.0-beta7,这是发布此答案时TestNG的最新版本]

  1. 首先需要创建一个自定义注释,用于定义类级别的超时

这里有一个完整的例子来说明这一点。

自定义注释如下所示:

import static java.lang.annotation.ElementType.TYPE;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;

@Retention(java.lang.annotation.RetentionPolicy.RUNTIME)
@Target({TYPE})
public @interface Timeout {
  long inMs() default 0;
}

使用上述自定义注释的测试类如下所示

import java.util.concurrent.TimeUnit;
import org.testng.annotations.Test;

@Timeout(inMs = 15)
public class TestClass1 {

  @Test
  public void sleepFor10Ms() throws InterruptedException {
    TimeUnit.MILLISECONDS.sleep(10);
  }

  @Test
  public void sleepFor20Ms() throws InterruptedException {
    TimeUnit.MILLISECONDS.sleep(20);
  }
}
import java.util.concurrent.TimeUnit;
import org.testng.annotations.Test;

@Timeout(inMs = 5)
public class TestClass2 {

  @Test
  public void sleepFor10Ms() throws InterruptedException {
    TimeUnit.MILLISECONDS.sleep(10);
  }

  @Test
  public void sleepFor20Ms() throws InterruptedException {
    TimeUnit.MILLISECONDS.sleep(20);
  }
}

注释变压器如下所示

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import org.testng.IAnnotationTransformer;
import org.testng.annotations.ITestAnnotation;

public class TimeoutSetter implements IAnnotationTransformer {

  @Override
  public void transform(
      ITestAnnotation annotation, Class testClass, Constructor testConstructor, Method testMethod) {
    if (testMethod == null) {
      return;
    }

    Timeout timeout = testMethod.getDeclaringClass().getAnnotation(Timeout.class);
    if (timeout == null) {
      return;
    }
    annotation.setTimeOut(timeout.inMs());
  }
}

套房文件是这样的

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Suite" verbose="2">
  <listeners>
    <listener class-name="com.rationaleemotions.stackoverflow.qn57307245.TimeoutSetter"/>
  </listeners>
  <test name="Test">
    <classes>
      <class name="com.rationaleemotions.stackoverflow.qn57307245.TestClass1"/>
      <class name="com.rationaleemotions.stackoverflow.qn57307245.TestClass2"/>
    </classes>
  </test>
</suite>

执行输出

... TestNG 7.0.0-beta7 by Cédric Beust (cedric@beust.com)
...









org.testng.internal.thread.ThreadTimeoutException: Method com.rationaleemotions.stackoverflow.qn57307245.TestClass1.sleepFor20Ms() didn't finish within the time-out 15

    at java.util.concurrent.ThreadPoolExecutor$Worker.unlock(ThreadPoolExecutor.java:652)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)






org.testng.internal.thread.ThreadTimeoutException: Method com.rationaleemotions.stackoverflow.qn57307245.TestClass2.sleepFor10Ms() didn't finish within the time-out 5

    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:132)
    at org.testng.internal.InvokeMethodRunnable.runOne(InvokeMethodRunnable.java:51)
    at org.testng.internal.InvokeMethodRunnable.run(InvokeMethodRunnable.java:41)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)





org.testng.internal.thread.ThreadTimeoutException: Method com.rationaleemotions.stackoverflow.qn57307245.TestClass2.sleepFor20Ms() didn't finish within the time-out 5

    at sun.misc.Unsafe.compareAndSwapInt(Native Method)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer.compareAndSetWaitStatus(AbstractQueuedSynchronizer.java:2303)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer.transferForSignal(AbstractQueuedSynchronizer.java:1674)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.doSignalAll(AbstractQueuedSynchronizer.java:1888)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.signalAll(AbstractQueuedSynchronizer.java:1957)
    at java.util.concurrent.ThreadPoolExecutor.tryTerminate(ThreadPoolExecutor.java:716)
    at java.util.concurrent.ThreadPoolExecutor.processWorkerExit(ThreadPoolExecutor.java:1014)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)

PASSED: sleepFor10Ms
FAILED: sleepFor20Ms
org.testng.internal.thread.ThreadTimeoutException: Method com.rationaleemotions.stackoverflow.qn57307245.TestClass1.sleepFor20Ms() didn't finish within the time-out 15
    at java.util.concurrent.ThreadPoolExecutor$Worker.unlock(ThreadPoolExecutor.java:652)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)

FAILED: sleepFor10Ms
org.testng.internal.thread.ThreadTimeoutException: Method com.rationaleemotions.stackoverflow.qn57307245.TestClass2.sleepFor10Ms() didn't finish within the time-out 5
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:132)
    at org.testng.internal.InvokeMethodRunnable.runOne(InvokeMethodRunnable.java:51)
    at org.testng.internal.InvokeMethodRunnable.run(InvokeMethodRunnable.java:41)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)

FAILED: sleepFor20Ms
org.testng.internal.thread.ThreadTimeoutException: Method com.rationaleemotions.stackoverflow.qn57307245.TestClass2.sleepFor20Ms() didn't finish within the time-out 5
    at sun.misc.Unsafe.compareAndSwapInt(Native Method)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer.compareAndSetWaitStatus(AbstractQueuedSynchronizer.java:2303)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer.transferForSignal(AbstractQueuedSynchronizer.java:1674)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.doSignalAll(AbstractQueuedSynchronizer.java:1888)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.signalAll(AbstractQueuedSynchronizer.java:1957)
    at java.util.concurrent.ThreadPoolExecutor.tryTerminate(ThreadPoolExecutor.java:716)
    at java.util.concurrent.ThreadPoolExecutor.processWorkerExit(ThreadPoolExecutor.java:1014)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)


===============================================
    Test
    Tests run: 7, Failures: 3, Skips: 0
===============================================


===============================================
Suite
Total tests run: 4, Passes: 1, Failures: 3, Skips: 0
===============================================


Process finished with exit code 0
周宏伯
2023-03-14

超时只能通过两种方式进行配置。1) 在每种试验方法水平上

本质上,testng中的测试类包含您的testng方法,这些方法是您对测试条件的断言(在您的例子中是基于超时的),所以它们只是普通的java类。

您可以尝试为每个testng类保留一个测试方法,并为该方法添加超时,也可以创建一个外部方法,该方法将根据方法执行所需的时间做出通过或失败的决定。

 类似资料:
  • 问题内容: 有人可以告诉我,如何在类级别调用方法吗? 假设我有一个如下所示的类,那么我们可以在类级别调用test1Method吗?如果不正确,请告诉我原因。 问题答案: 不,您不能在类下直接拥有方法调用语句或任何其他语句。根据JLS第8节-类的规定: 类的主体声明成员(字段和方法以及嵌套的类和接口),实例和静态初始化器以及构造函数(第8.1.6节)。 您必须在那些成员(某些方法),初始化程序或构造

  • 问题内容: 我有一个用于Go包的测试套件,该套件实现了十二个测试。有时,套件中的一项测试失败了,我想单独重新运行该测试,以节省调试时间。这可能吗,还是每次都必须为此编写一个单独的文件? 问题答案: 使用该标志运行特定的测试。该标志记录在go工具文档的测试标志部分中:

  • 我接手了一个旧的java项目。原来的设计师已经走了。在这个项目中,它以静态的方式使用Log4j,像这样: } 然后另一个类可以轻松地使用和。信息记录器和错误记录器被配置为写入不同的文件。 但是在Log4j2中,找不到LoggingEvent类。 所以问题是,如果我想使用Log4j2,我应该如何修改这个类?(可能使用log4j2包中提供的Log4j 1.x桥?) 这样使用记录器合理吗?似乎比每个类创

  • 问题内容: 我知道这是一个不好的做法,但是需要完成,否则我需要切换到。有没有一种类似于JUnit 3的testSuite的方法来指定要在类中运行的测试的顺序? 问题答案: 如果你确定你 真的 想这样做:有可能是一个更好的办法,但是这是我能拿出… JUnit4有一个注释:它使您可以覆盖测试的默认Runner。 在您的情况下,您将需要创建一个特殊的子类,并重写以按照您希望它们执行的顺序返回测试。例如,

  • 当将DataProvider与多个TestNG方法一起使用时,每个方法都按顺序与所有数据集一起运行。相反,我希望迭代数据集,并在每次迭代中执行所有方法。我不关心结果是否显示了每个测试方法的结果或每个方法运行的总结。 我已经试过了 所需的结果:

  • 我不熟悉使用selenium和java实现页面对象模型自动化。我使用页面对象模型,将每个页面作为一个类,并将该页面中的操作作为方法。使用excel保存读取的测试数据。我有一个测试,可以使用各种参数来搜索客户,如客户编号、政策编号、姓氏、名字、WebReference、电子邮件等等。。。。。。现在,我必须在方法签名中提供所有参数,否则测试将失败,并出现数据提供程序不匹配错误。我有一个GetData方