2009-01-08 147 views
98

我正在使用JUnit 4.4和Maven,並且我有大量的長時間運行的集成測試。在Maven構建中並行運行junit測試?

當談到並行化測試套件時,有幾個解決方案允許我在單個測試類中並行運行每個測試方法。但所有這些都要求我以這種或那種方式改變測試。

我真的認爲這將是一個更簡潔的解決方案,在X線程中並行運行X個不同的測試類。我有數百個測試,所以我並不在乎對單個測試類進行線程化。

有沒有辦法做到這一點?

回答

36

從junit 4.7現在可以在不使用TestNG的情況下並行運行測試。實際上,從4.6開始就可以實現,但在4.7版本中有一些修復將會使它成爲一個可行的選擇。您也可以使用彈簧進行平行測試,您可以閱讀有關信息here

+1

鏈接頁面顯示「對於大多數雙核解決方案來說,使用並行線程運行目前永遠不會比運行非線程更快」。那仍然是這樣嗎? – Raedwald 2011-04-04 14:00:33

+2

我會認爲,如果你的測試做任何IO,他們仍然會受益。例如,如果你的單元測試更像集成測試並且碰到數據庫,那麼並行運行應該加速它們。 – Dave 2011-05-04 18:46:41

4

TestNG can do that(這是我的第一個反應 - 然後我看到你已經有很多測試用例)。

對於JUnit,請看parallel-junit

+3

不幸的是,這不是我問的問題的答案。 parallel-junit只能在單個測試類中運行。 TestNG也只能在一個類中運行,而我的測試不是TestNG測試。 – krosenvold 2009-01-08 11:42:33

+0

@PlatinumAzure:我更新了鏈接。我不知道這個項目是如何維護的。另一個問題最近被問到[在幾臺機器上分發junit測試執行](http://stackoverflow.com/questions/10690587/running-parallel-junit-tests-on-multiple-remote-machines)。 – philant 2012-05-24 07:16:04

-2

您可以在一分鐘內將您的測試更改爲TestNg測試(您只需更改導入),TestNG是最好的並行測試。

-2

你可以試試Gridgain,它可以讓你在計算網格上運行你的測試。

+1

我嘗試過GridGain解決方案,並遇到兩個主要問題。首先,你必須告訴GridGain從網格任務的類路徑中排除GridGain也使用的任何東西,例如Spring和許多Apache Commons的東西。其次,網絡類加載雖然是一個絕妙的想法,但不適用於想要搜索類路徑的庫,例如Spring – 2010-12-19 23:24:14

5

tempus-fugit提供了類似的內容,請查看文檔以瞭解詳細信息。它依賴於JUnit 4.7,您只需將您的測試標記爲@RunWith(ConcurrentTestRunner)即可。

乾杯

3

您可以檢查出的開源庫 - Test Load Balancer。它完全符合你的要求 - 並行運行不同的測試類。這集成在ant-junit級別,所以你不必改變你的測試。我是圖書館的作者之一。

另外,請考慮不要在線程中運行它們,因爲您可能需要一個進程級別的沙箱。例如,如果您在集成測試中擊中數據庫,則不希望一次測試失敗,因爲另一次測試會在另一個線程中添加一些數據。大多數情況下,測試不會寫在這裏。

最後,到現在爲止如何解決了這個問題?

62

使用Maven插件:

<build> 
    <plugins> 
    <plugin> 
     <groupId>org.apache.maven.plugins</groupId> 
     <artifactId>maven-surefire-plugin</artifactId> 
     <version>2.7.1</version> 
     <configuration> 
      <parallel>classes</parallel> 
      <threadCount>5</threadCount> 
     </configuration> 
    </plugin> 
    </plugins> 
</build> 
9

通過JUnit的實驗ParallelComputer亞軍啓發我已經建立了自己的ParallelSuiteParallelParameterized亞軍。使用這些跑步者可以輕鬆地並行測試套件和參數化測試。

ParallelSuite.java

public class ParallelSuite extends Suite { 

    public ParallelSuite(Class<?> klass, RunnerBuilder builder) throws InitializationError { 

     super(klass, builder); 

     setScheduler(new RunnerScheduler() { 

      private final ExecutorService service = Executors.newFixedThreadPool(4); 

      public void schedule(Runnable childStatement) { 
       service.submit(childStatement); 
      } 

      public void finished() { 
       try { 
        service.shutdown(); 
        service.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS); 
       } catch (InterruptedException e) { 
        e.printStackTrace(System.err); 
       } 
      } 
     }); 
    } 
} 

ParallelParameterized。java

public class ParallelParameterized extends Parameterized { 

    public ParallelParameterized(Class<?> arg0) throws Throwable { 

     super(arg0); 

     setScheduler(new RunnerScheduler() { 

      private final ExecutorService service = Executors.newFixedThreadPool(8); 

      public void schedule(Runnable childStatement) { 
       service.submit(childStatement); 
      } 

      public void finished() { 
       try { 
        service.shutdown(); 
        service.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS); 
       } catch (InterruptedException e) { 
        e.printStackTrace(System.err); 
       } 
      } 
     }); 
    } 
} 

用法很簡單。只需將@RunWith註釋值賦予其中一個並行*類。

@RunWith(ParallelSuite.class) 
@SuiteClasses({ATest.class, BTest.class, CTest.class}) 
public class ABCSuite {} 
2

您可以使用由Junit自身提供的ParallelComputer並行運行測試。這裏有一個小小的部分讓你開始。

Class[] cls = { TestCase1.class, TestCase2.class }; 
Result result = JUnitCore.runClasses(ParallelComputer.classes(), cls); 
List<Failure> failures = result.getFailures(); 

當您需要從代碼運行測試時,這將有所幫助,因爲它不依賴於Maven或任何其他構建管理工具。

請注意,這將並行運行所有測試用例,如果您在不同測試用例之間存在任何依賴關係,可能會導致誤報。無論如何你都不應該有相互依存的測試。