关于java:JUnit:是否存在执行并行测试的明智方法?

 2020-08-01 

JUnit: is there a smart way to perform parallel testing?

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

我的初稿不起作用:

1
2
3
4
5
6
7
@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不是在主线程中调用,而是在并行线程中调用?

我的第二稿起作用了,因为该测试用例按预期失败了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
@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;
    }
}

完成以下操作:

  • testcaseOk中,要测试的代码被嵌入到try / catch块中,并且每个AssertionError被重新抛出。
  • parallelTests包含20次testcaseOk
  • ExecutorService执行所有parallelTests
  • 如果在testcaseOk中抛出AssertionError,它将被收集到allThrownAssertionErrors中。
  • 如果allThrownAssertionErrors包含任何AssertionError,它将被抛出并且测试用例parallelTestOk()将失败。 否则就可以了。
  • 我的parallelTestOk()似乎很复杂。 有没有更简便,更智能的方法(无需使用TestNG)?


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

    这将正确地通过测试:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    @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();
        }
    }