How to make xUnit for parallel theory work?

I have a test (Theory) that is slow and a bunch of test cases for it. Therefore, I want them to run at the same time.

I created a simple example:

[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 }; } } 

Command line to run the test:

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

And the result:

 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 

This is a pretty serial number. I am sure that this can be done in parallel.

+6
source share
2 answers

This is currently not possible with xUnit 2.1. In accordance with the parallelization documents ,

By default, each test class is a unique test collection. Tests inside the same test class will not work in parallel to each other.

That the docs are clearly not clear:

  • xUnit's smallest "parallelizable" module is a collection
  • there is no possibility for tests in the same class in different collections

In addition to this, it is impossible to have parallel theories, because theories cannot be divided into several classes.


In your case, this means that you have at least two options:

  • Restore your code under the test so that all the time spent on so much time is distracted. For example, let's say you need to run some business logic and then make a database call. If you can separate the tested business logic in another class, you can run your theory against this (not in parallel, but in <1 ms) and separately check the slow data access code.

  • If you have few test cases, just create a new class for each test case and use Fact instead of Theory . You can even place them in one file. This is more verbose, and you lose the “cool” factor in using theories, but you get parallel execution.

+5
source

Although this is not possible directly with xUnit, you can get around this if you need to. With drawbacks, you must manually determine the number of parallel executions through classes, so if you want to parallelize it across two threads, you need to create two classes.

 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); } } 

In this example, I defined a property in ParellelTheoryBase , which is the base class for real test classes. Then ParallelTheory_1of2 and ParallelTheory_2of2 inherit access to testValues from this class. Now Theory uses this theoryData to run the test, and it selects only data with odd or even ( index % 2 == 1 or index % 2 == 0 ) from the list.

It gets into the Visual Studio Test Explorer: Visual Studio Test Explorer

And executed in parallel:

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

This may be the solution when it is not easy for you to know in advance how much test data you have. I use this, for example, when integrating file parser testing, where the input is any file in the directory, and new new files will be automatically selected for tests.

In your example, I think you can easily change the MyTestData attribute to accept the parameters for totalCountParallels and currentIndex .

+3
source

All Articles