我有一个用于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浏览器”。您不需要为提交到线程池的每个作业启动新的浏览器。
这里有一些有关如何完成此操作的想法。
具有BlockingQueue
个TestCase
对象。然后,每个线程都会初始化其浏览器,然后从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/