我有一个用于Web测试的应用程序(基于Selenium,但这在这里应该没什么大不了),它可以连续执行许多测试用例。它需要几个小时才能完成,并且测试用例的数量在增加,所以我想使用多个Web浏览器实例来并行执行几个测试用例。测试用例彼此之间没有依赖性。

非常简化,看起来像这样:

TestExecutor executor = new TestExecutor(new FirefoxDriver());
for (TestCase test: tests) {
    executor.execute(test);
    // use results here
}


现在我不知道到底该如何并行化。我可以轻松地创建几个与多个Web浏览器连接为Callables的TestExecutor,并使用Executors,CompletitionServices和其他不错的帮助程序类,但是我该如何做:


一旦准备好使用先前的TestCase,将新的TestCase传递给TestExecutor? Callable中的call()方法不带任何参数,因此我可能必须在TestExecutor类中实现一些setNextTestCase()才能实现这一点,但我认为这并不好。有更好的选择吗?
重用TestExecutor实例来执行下一个测试用例?由于每个TestExecutor实例都需要一个Web浏览器实例,因此如果要为每个测试用例创建一个新的TestExecutor,则初始化它会花费很长时间,并且会导致屏幕上闪烁许多窗口。

最佳答案

一旦准备好使用先前的TestCase,将新的TestCase传递给TestExecutor?


如果我了解您,这是一个常见问题。您在线程池中有多个线程,但是每个线程都有一些上下文-在这种情况下为“ Web浏览器”。您不需要为提交到线程池的每个作业启动新的浏览器。

这里有一些有关如何完成此操作的想法。


具有BlockingQueueTestCase对象。然后,每个线程都会初始化其浏览器,然后从TestCase对象的队列中出队,直到队列为空或某些shutdown布尔值设置为true。您可以将TestExecutor对象提交到线程池中,但是它们将通过自己的队列对TestCase对象进行出队。您不会将TestCase提交到线程池。

BlockingQueue<TestCase> testCaseQueue = new LinkedBlockingQueue<>();
for (TestCase test: tests) {
    testCaseQueue.add(test);
}
// now make your executors and run them in a thread-pool
TestExecutor testExecutor =
     new TestExecutor(new FirefoxDriver(), testCaseQueue);
ExecutorService threadPool = Executors.newCachedThreadPool();
threadPool.submit(testExecutor);
...
// once you've submitted your last executor, you shutdown the pool
threadPool.shutdown();

...
// inside of the executor, they dequeue tests from `testCaseQueue`
while (!shutdown) {
    TestCase testCase = testCaseQueue.poll(0, TimeUnit.MILLISECONDS);
    if (testCase == null) {
       break;
    }
    ...
}

另一个想法是将TestCase提交到线程池,并使用ThreadLocal获取先前配置的测试浏览器。这不是最佳选择,因为在完成测试后很难适当地终止浏览器。

关于java - 重用工作程序实例来处理多项任务,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/18960454/

10-12 04:07