【问题标题】:JUnit: is there a smart way to perform parallel testing?JUnit:有没有一种聪明的方法来执行并行测试?
【发布时间】:2016-01-18 15:01:17
【问题描述】:

在我的 JUnit 测试中,我想执行并行测试。

我的初稿不行:

@Test
public void parallelTestNotOk() {
    ExecutorService executor = Executors.newFixedThreadPool(10);
    Runnable testcaseNotOk = () -> fail("This failure is not raised.");
    IntStream.range(0, 20).forEach(i -> executor.submit(testcaseNotOk));
    executor.shutdown();
}

虽然每个testcaseNotOk 都失败了,但这个测试用例成功了。为什么?因为fail不是在主线程中调用的,而是在并行线程中调用的?

我的第二稿有效,因为这个测试用例按预期失败:

@Test
public void parallelTestOk() throws InterruptedException {
    ExecutorService executor = Executors.newFixedThreadPool(10);
    Callable<AssertionError> testcaseOk = () -> {
        try {
            fail("This failure will be raised.");
        } catch (AssertionError e) {
            return e;
        }
        return null;
    };
    List<Callable<AssertionError>> parallelTests = IntStream
            .range(0, 20).mapToObj(i -> testcaseOk)
            .collect(Collectors.toList());
    List<AssertionError> allThrownAssertionErrors = executor.invokeAll(parallelTests)
      .stream().map(future -> {
        try {
            return future.get();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }).filter(assertionError -> assertionError != null).collect(Collectors.toList());
    executor.shutdown();
    for (AssertionError e : allThrownAssertionErrors) {
        throw e;
    }
}

以下内容已完成:

  1. 在 testcaseOk 中,要测试的代码嵌入到 try/catch 块中,并且每个 AssertionError 都会重新抛出。
  2. parallelTests 包含 20 次 testcaseOk。
  3. ExecutorService 执行所有parallelTests。
  4. 如果在testcaseOk 中抛出AssertionError,它将被收集到allThrownAssertionErrors。
  5. 如果allThrownAssertionErrors 包含任何AssertionError,它将被抛出并且测试用例parallelTestOk() 将失败。否则就OK了。

我的parallelTestOk() 似乎很复杂。有没有更简单、更智能的方法(不使用 TestNG)?

【问题讨论】:

  • Concurrent JUnit testing的可能重复
  • 建议的副本已过时,因为自 4.7 以来 JUnit 已包含一个并行运行器(可轻松用于 Maven 和 Gradle)。

标签: java multithreading junit


【解决方案1】:

您的问题是您从不检查 Future 的值以查看是否引发了异常。

这将正确地使测试失败:

@Test
public void parallelTestWillFail() throws InterruptedException, ExecutionException {
    ExecutorService executor = Executors.newFixedThreadPool(10);
    Runnable testcaseNotOk = () -> fail("This failure IS raised.");
    List<Future<?>> futures = IntStream.range(0, 20)
                                .mapToObj(i -> executor.submit(testcaseNotOk))
                                .collect(Collectors.toList());
    executor.shutdown();
    for(Future<?> f : futures){
        f.get();
    }
}

【讨论】:

    猜你喜欢
    • 2013-11-27
    • 1970-01-01
    • 2020-08-28
    • 2015-04-07
    • 2021-03-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多