2013-09-23 27 views
1

我有一個Web測試應用程序(基於Selenium,但這不應該太重要),它會連續執行很多測試用例。完成這個過程需要花費幾個小時,測試用例的數量也會增加,所以我想使用多個Web瀏覽器實例並行執行多個測試用例。測試用例彼此沒有依賴關係。重用一個工作者實例來處理幾個任務

非常簡單的,它看起來像這樣:

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

現在我不知道到底如何並行這一點。我可以輕鬆地創建連接到幾個網絡瀏覽器作爲可調用幾個TestExecutors和使用執行人,CompletitionServices和其他不錯的輔助類,但我怎麼:

  • 通過一項新的TestCase的TestExecutor一旦它準備與以前的TestCase ? Callable中的call()方法不需要任何參數,所以我可能必須在TestExecutor類中實現一些setNextTestCase()來實現這個功能,但我覺得它不是很好。有沒有更好的選擇?

  • 重複使用TestExecutor實例執行下一個測試用例?由於每個TestExecutor實例都需要一個Web瀏覽器實例,因此初始化該實例需要很長時間,並且如果我要爲每個測試用例創建一個新的TestExecutor,則會導致屏幕上出現許多窗口閃爍。

回答

4

將一個新的TestCase傳遞給TestExecutor一旦它準備好了前面的TestCase?

這是一個常見的問題,如果我理解你。線程池中有多個線程,但每個線程都有一些上下文 - 在本例中爲「Web瀏覽器」。您不希望爲提交給線程池的每個作業啓動新的瀏覽器。

以下是關於如何完成此操作的一些想法。

  • BlockingQueue of TestCase對象。然後,每個線程初始化其瀏覽器,然後從TestCase對象的隊列中出列隊列,直到隊列爲空或某個關閉布爾值設置爲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以獲取測試以前配置的瀏覽器。這並不是最佳選擇,因爲當測試完成時,它很難正確終止瀏覽器。

+0

我明白了,謝謝。但在這種情況下,我沒有明白使用ExecutorService的意義。我們從中獲得什麼?在運行期間沒有提交任何新任務(在這種情況下是TestExecutors),因此ExecutorService實際上沒有任何計劃。我可以創建一些TestExecutors(像你所建議的那樣在c'tor中傳入testCaseQueue)作爲Thread實例並啓動它們中的每一個。對? – Pinni

+0

是的,它不是必要的@Pinni。很多人總是使用'ExecutorService'而不是自己實例化'Thread'。 – Gray

0

我會建議設立的TestExecutors一個Queue/List。然後創建一個包裝TestCaseCallable/Runnable。您ExecutorService將具有與TestExecutorsList相同的線程數。 Runnable的第一步是從Queue中檢索/彈出TestExecutor。它會利用執行者進行測試,然後在完成時將其放回隊列中。

相關問題