2015-09-21 10 views
6

我有一個很慢的測試(理論)和一堆測試用例。 所以我想讓它們同時運行。如何讓xUnit運行一個並行的理論?

我創建了一個簡單的例子:

[Theory] 
[MyTestData] 
public void MyTheory(int num, int sleep) 
{ 
    Console.WriteLine("{0:HH:mm:ss.ffff} - Starting {1} - Sleeping {2}", DateTime.Now, num, sleep); 
    Thread.Sleep(sleep); 
    Console.WriteLine("{0:HH:mm:ss.ffff} - Finished {1} - Sleeping {2}", DateTime.Now, num, sleep); 
} 

[AttributeUsage(AttributeTargets.Method)] 
public class MyTestDataAttribute : DataAttribute 
{ 
    public override IEnumerable<object[]> GetData(MethodInfo testMethod) 
    { 
     yield return new object[2] { 1, 5000 }; 
     yield return new object[2] { 2, 2000 }; 
     yield return new object[2] { 3, 4000 }; 
    } 
} 

命令行運行測試:

"\packages\xunit.runner.console.2.0.0\tools\xunit.console" "\Projects\xUnitTest\xUnitTest\bin\Debug\xUnitTest.dll" -parallel all > xUnitResult.txt 

而結果:

xUnit.net console test runner(64-bit.NET 4.0.30319.42000) 
Copyright(C) 2015 Outercurve Foundation. 

Discovering: xUnitTest 
Discovered: xUnitTest 
Starting: xUnitTest 
21:55:39.0449 - Starting 2 - Sleeping 2000 
21:55:41.0627 - Finished 2 - Sleeping 2000 
21:55:41.0783 - Starting 1 - Sleeping 5000 
21:55:46.0892 - Finished 1 - Sleeping 5000 
21:55:46.0892 - Starting 3 - Sleeping 4000 
21:55:50.0989 - Finished 3 - Sleeping 4000 
Finished: xUnitTest 

=== TEST EXECUTION SUMMARY === 
    xUnitTest Total: 3, Errors: 0, Failed: 0, Skipped: 0, Time: 11,137s 

這是非常序列。 我相信可以做到平行。

+6

https://xunit.github.io/docs/running-tests-in-parallel.html –

+1

Btw,'[MemberData(nameof(MyTestData))]]'比創建自定義屬性更清潔,在我看來。 –

回答

5

從xUnit 2.1開始,這是不可能的。根據parallelization docs

默認情況下,每個測試類是一個獨特的測試集合。相同測試類中的測試不會相互平行運行。

什麼文檔不作出明確清楚的是:

  • 在xUnit的最小的「並行」單元是一家集
  • 沒有辦法在同一類的測試是在不同的集合

通過擴展,不可能有並行化的理論,因爲理論不能分成多個類。


在你的情況,這意味着至少有兩個選項:

  • 重構測試下你的代碼,這樣無論是採取了這麼多時間抽象化了。例如,假設您必須運行一些業務邏輯,然後進行數據庫調用。如果您可以將可測試的業務邏輯分離爲另一個類,那麼可以針對該原理運行理論(不是並行的,但是在< 1 ms內),並分別測試慢速數據訪問代碼。

  • 如果您的測試用例足夠少,只需爲每個測試用例創建一個新類,然後使用Fact而不是Theory。你甚至可以把它們放在一個文件中。它更冗長,你失去了使用理論的「酷」因素,但你會得到並行執行。

3

儘管不能直接與xUnit一起使用,但如果需要的話,您可以解決此問題。有缺點,就像你必須手動定義通過類的並行執行次數一樣,所以如果你想通過兩個線程並行執行它,你需要創建兩個類。

public abstract class ParellelTheoryBase 
{ 
    public static List<int> testValues = new List<int> {1, 2, 3, 4, 5, 6}; 
} 

public class ParallelTheory_1of2 : ParellelTheoryBase 
{ 
    public static List<object[]> theoryData = testValues.Where((data, index) => index % 2 == 0).Select(data => new object[] { data }).ToList(); 

    [Theory] 
    [MemberData(nameof(theoryData))] 
    public void DoSomeLongRunningAddition(int data) 
    { 
     Assert.True(data < 7); 
     Thread.Sleep(5000); 
    } 
} 

public class ParallelTheory_2of2 : ParellelTheoryBase 
{ 
    public static List<object[]> theoryData = testValues.Where((data, index) => index % 2 == 1).Select(data => new object[] { data }).ToList(); 

    [Theory] 
    [MemberData(nameof(theoryData))] 
    public void DoSomeLongRunningAddition(int data) 
    { 
     Assert.True(data < 7); 
     Thread.Sleep(5000); 
    } 
} 

在本例中,我已經定義在ParellelTheoryBase的屬性,它是實際的測試類的基類。 然後,ParallelTheory_1of2ParallelTheory_2of2繼承該類訪問testValues。現在,Theory使用此theoryData進行測試執行,並且它僅從列表中選擇奇數或偶數(index % 2 == 1index % 2 == 0)數據。

它得到在Visual Studio的測試資源管理拾起: Visual Studio test explorer

而在並行運行:

[xUnit.net 00:00:00.3397963] Starting 
[xUnit.net 00:00:15.5696617] Finished 

,這可能是一個解決方案,這是不容易在事前多少測試數據就知道你有。例如,我用它來集成測試一個文件解析器,其中輸入是目錄中的任何文件,新添加的文件將自動被選中用於測試。

在您的示例中,我認爲您可以輕鬆修改MyTestData屬性以接受totalCountParallelscurrentIndex的參數。