如何让 TestNG 方法在达到超时后立即终止?
How to get TestNG method to terminate as soon as time-out is reached?
我必须为有时在加载页面时无限期挂起的网站编写测试。我想写一个方法,在它开始后 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
如何让测试在达到时间限制后立即失败?
TLDR;
不要捕获 InterruptedException
只需放入 throws 子句。
随着 TestNG 的工作(在这种情况下),框架将创建一个新的单线程 executorService,提交一个等待终止的工作程序。如果测试 运行 没有完成,工人将抛出 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
标志将为 false。
所以这会有所帮助:
@Test(timeOut = 4000)
public void test() throws InterruptedException {
Thread.sleep(5000);
System.out.println("I don't want this to print");
}
我必须为有时在加载页面时无限期挂起的网站编写测试。我想写一个方法,在它开始后 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
如何让测试在达到时间限制后立即失败?
TLDR;
不要捕获 InterruptedException
只需放入 throws 子句。
随着 TestNG 的工作(在这种情况下),框架将创建一个新的单线程 executorService,提交一个等待终止的工作程序。如果测试 运行 没有完成,工人将抛出 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
标志将为 false。
所以这会有所帮助:
@Test(timeOut = 4000)
public void test() throws InterruptedException {
Thread.sleep(5000);
System.out.println("I don't want this to print");
}