首页 > 解决方案 > 一旦达到超时,如何让 TestNG 方法终止?

问题描述

我必须为有时在加载页面时无限期挂起的网站编写测试。我想写一个在它开始运行后 20 分钟超时的方法。

但是当我尝试编写这样的代码时 -

@Test(timeOut=4000)
public void test() {
    try { Thread.sleep(5000); } catch (InterruptedException e) {}
    System.out.println("I don't want this to print.");
}

测试打印“我不想打印”。然后由于预期的异常而失败-org.testng.internal.thread.ThreadTimeoutException: Method didn't finish within the time-out 4000

一旦达到时间限制,我怎样才能让测试失败?

标签: javatestng

解决方案


TLDR;
不要捕获InterruptedException只是放在 throws 子句中。

当 TestNG 工作时(在这种情况下),框架将创建一个新的单线程executorService,提交一个等待终止的 worker。如果测试运行未完成,工人将抛出org.testng.internal.thread.ThreadTimeoutException. 相关源代码为:

org.testng.internal.MethodInvocationHelper

  private static void invokeWithTimeoutWithNewExecutor(
      ITestNGMethod tm,
      Object instance,
      Object[] parameterValues,
      ITestResult testResult,
      IHookable hookable)
      throws InterruptedException, ThreadExecutionException {
    ExecutorService exec = ThreadUtil.createExecutor(1, tm.getMethodName());

    InvokeMethodRunnable imr =
        new InvokeMethodRunnable(tm, instance, parameterValues, hookable, testResult);
    Future<Void> future = exec.submit(imr);
    exec.shutdown();
    long realTimeOut = MethodHelper.calculateTimeOut(tm);
    boolean finished = exec.awaitTermination(realTimeOut, TimeUnit.MILLISECONDS);

    if (!finished) {
      exec.shutdownNow();
      ThreadTimeoutException exception =
          new ThreadTimeoutException(
              "Method "
                  + tm.getQualifiedName()
                  + "() didn't finish within the time-out "
                  + realTimeOut);
      testResult.setThrowable(exception);
      testResult.setStatus(ITestResult.FAILURE);
    } else {
      Utils.log(
          "Invoker " + Thread.currentThread().hashCode(),
          3,
          "Method " + tm.getMethodName() + " completed within the time-out " + tm.getTimeOut());

      // We don't need the result from the future but invoking get() on it
      // will trigger the exception that was thrown, if any
      try {
        future.get();
      } catch (ExecutionException e) {
        throw new ThreadExecutionException(e.getCause());
      }

      testResult.setStatus(ITestResult.SUCCESS); // if no exception till here then SUCCESS.
    }
  }

重点是:

ExecutorService exec = ThreadUtil.createExecutor(1, tm.getMethodName());
// ... and
boolean finished = exec.awaitTermination(realTimeOut, TimeUnit.MILLISECONDS);

在测试方法中处理的java.util.concurrent.ExecutorService.awaitTermination(...)方法抛出。InterruptedException因此,测试方法不会终止,但finished标志将为假。

所以它会有所帮助:

@Test(timeOut = 4000)
public void test() throws InterruptedException {
    Thread.sleep(5000);
    System.out.println("I don't want this to print");
}

推荐阅读