如果部分测试时间过长,如何从 JUnit 测试返回到主方法



我尝试从我的main()方法运行 junit:

public static void main(String... args) throws ClassNotFoundException, 
       IOException {
  //...
  logger.debug("className " + className + "methodName " + methodName);
  Request request = Request.method(Class.forName(className), methodName);
  return new JUnitCore().run(request);
}

我有一个包含 10 个命令的 E2E 测试(比如说)。它由 JUnit 运行,我想将命令的运行时间限制为 3-5 到 X millis(其中 X 在运行时确定)。如果它的运行时间超过 X,我想返回main()并打印一些东西。

我已经尝试过System.exit()但它关闭了整个应用程序。我试过了:

public void setTimeOut(String criticalBlockTimeOutMilli) {
    if (criticalBlockTimeOutMilli != null) {
        TimerTask timerTask = new TimerTask() {
            @Override
            public void run() {
                E2eResult e2eResult = E2eResult.getInstance();
                e2eResult.status = E2eStatus.TIMEOUT;
                //System.exit(2);
            }
        };
        new Timer().schedule(timerTask, Long.parseLong(criticalBlockTimeOutMilli));
    }
}
public void setTimeOut(final Thread thread, String criticalBlockTimeOutMilli) {
    if (criticalBlockTimeOutMilli != null) {
        TimerTask timerTask = new TimerTask() {
            @Override
            public void run() {
                E2eResult e2eResult = E2eResult.getInstance();
                e2eResult.status = E2eStatus.TIMEOUT;
                thread.interrupt();
            }
        };
        new Timer().schedule(timerTask, Long.parseLong(criticalBlockTimeOutMilli));
    }
}

但即使超过限制,主线程也会继续运行测试。你有什么建议?

单元测试可能不是解决此类性能测试的最佳方法。但是,如果有某种原因必须这样做,请继续阅读...

使用ExecutorService运行所需的命令,并具有给定的超时。如果超时到期,请抛出您自己的异常,您可以在主线程中捕获该异常:

@Test
public void yourTest() throws Exception {
  // Do commands 1-2
  ExecutorService service = Executors.newSingleThreadExecutor();
  Future<Void> result = service.submit(new Callable<Void>() {
    @Override
    public Void call() throws Exception {
      // call commands 3-5
      return null;
    }
  });
  try {
    result.get(42, TimeUnit.MILLISECONDS);
  } catch (TimeoutException e) {
    throw new YourOwnException();
  }
  service.shutdown();
  // Do commands 6-10
}

一种相当简单的机制是使用BlockingQueue来指示测试已完成。如果你发现它没有,你可以interrupt它。仅当测试正确响应中断时,这才有效。

// Send FINISHED down this queue when test completes.
final BlockingQueue<Object> finished = new ArrayBlockingQueue<>(1);
// FINISHED cookie.
static final Object FINISHED = new Object();
public void test() throws InterruptedException {
    Thread test = new Thread(new Runnable() {
        @Override
        public void run() {
            // Do your stuff.
            // ...
            // Signal we finished.
            finished.add(FINISHED);
        }
    });
    // Start the test in it's own thread.
    test.start();
    try {
        // Wait for your time.
        if (FINISHED == finished.poll(5, TimeUnit.MILLISECONDS)) {
            // It completed! No problems.
        } else {
            // It hasn't finished! Interrupt it.
            test.interrupt();
        };
    } catch (InterruptedException ex) {
        // We were interrupted! Do something.
        test.interrupt();
        // Rethrow it.
        throw(ex);
    }
}

您也可以通过添加"已启动"消息来扩展此机制,以确保测试线程至少有机会运行。

相关内容

  • 没有找到相关文章

最新更新