I am looking for ways to run test suites in parallel.
I am aware of .testrunconfig
setting. This allows you to multiplex on the numb
What I found is that C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE\CommonExtensions\Microsoft\TestWindow\vstest.console.exe
will run parallel tests with a .testsettings
file which looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<TestSettings name="TestSettings1" id="21859d0f-7bdc-4165-b9ad-05fc803c9ee9" xmlns="http://microsoft.com/schemas/VisualStudio/TeamTest/2010">
<Description>These are default test settings for a local test run.</Description>
<Deployment enabled="false" />
<Execution parallelTestCount="8">
<TestTypeSpecific>
<UnitTestRunConfig testTypeId="13cdc9d9-ddb5-4fa4-a97d-d965ccfc6d4b">
<AssemblyResolution>
<TestDirectory useLoadContext="true" />
</AssemblyResolution>
</UnitTestRunConfig>
</TestTypeSpecific>
<AgentRule name="Execution Agents">
</AgentRule>
</Execution>
</TestSettings>
Reference can be found here http://msdn.microsoft.com/en-us/library/vstudio/jj155796.aspx
The above answers definitely helped clarify things for me, but, this point from John Koerner's blog: https://johnkoerner.com/vs2015/parallel-test-execution-in-visual-studio-2015-update-1-might-not-be-what-you-expect/ was the bit we were missing.
"Parallel test execution leverages the available cores on the machine, and is realized by launching the test execution engine on each available core as a distinct process, and handing it a container (assembly, DLL, or relevant artifact containing the tests to execute), worth of tests to execute."
--> "The separate container bit is the piece I was missing. In order to get my tests to run in parallel, I needed to split up my tests into separate test assemblies. After doing that, I saw that the tests in different assemblies were running in parallel."
So yeah, we got the tests running in parallel in VSTS by using their handy 'run in parallel' flag, but it wasn't enough, we had to split our tests up into separate test projects. Logically grouped of course, not a project-per-test which would be ridiculous
Visual Studio 2015 Update 1 adds this. https://docs.microsoft.com/visualstudio/releasenotes/vs2015-update1-vs#misc
For Update 2, there is a UI toggle button in the toolbar at the top of the Test Explorer pane (between the 'grouping' and 'search' boxes).
For Update 1, Set the following in the .runsettings
<?xml version="1.0" encoding="utf-8"?>
<RunSettings>
<RunConfiguration>
<MaxCpuCount>0</MaxCpuCount>
</RunConfiguration>
</RunSettings>
The value for MaxCpuCount has the following semantics:
• ‘n’ (where 1 <= n <= number of cores) : upto ‘n’ processes will be launched.
• ‘n’ of any other value : The number of processes launched will be as many as the available cores on the machine.
Most of the answers on this page forget to mention that MSTest parallelizes tests in separate assemblies. You have to split your unittests into multiple .dll's to paralelize it.
But! The recent version - MSTest V2 - now CAN parallelize "in-assembly" (yay!) you just need to install a couple of nuget packages in your test project - TestFramework and TestAdapter - like described here https://blogs.msdn.microsoft.com/devops/2018/01/30/mstest-v2-in-assembly-parallel-test-execution/
And then simply add this to your test project
[assembly: Parallelize(Workers = 4, Scope = ExecutionScope.ClassLevel)]
EDIT: You can also disable parallel execution for a specific test using [DoNotParallelize]
on a test method.
You can get up to 5 by using the method from the Visual Studio Team Test Blog
Keep in mind that there may be concurrency issues using this, as MSTest doesn't completely isolate each test (statics carry over, for example, making things interesting for code meant to run once).
(No idea why the limit is 5, but MSTest will not run them in parallel if parallelTestCount
is set to more than 5. As per the comments below, this rule apparently changes with Visual Studio 2013)
In the AsyncExecutionContext method add the following:
public static void AsyncExecutionContext(DataRow currentRow, AsyncExecutionTask test)
{
if(!BatchStarted)
{
foreach(DataRow row in currentRow.Table)
{
Task testTask = new Task(()=> { test.Invoke(row); });
AsyncExecutionTests.Add(row[0].ToString(), testTask);
testTask.Start();
}
BatchStarted = true;
}
Task currentTestTask = AsyncExecutionTests[row[0].ToString()];
currentTestTask.Wait();
if(currentTestTask.Exception != null) throw currentTestTask.Exception;
}
Now use the class like so:
[TestMethod]
public void TestMethod1()
{
ParallelTesting.AsyncExecutionContext(TestContext.DataRow, (row)=>
{
//Test Logic goes here.
}
);
}
Note: You will have to do some tinkering with exceptions to get them to bubble correctly (you may have an aggregate exception here, you'll need the first exception from it). The amount of time displayed that each test takes to execute will no longer be accurate. You will also want to cleanup the ParallelTesting class after the last row is completed.
How it works: The test logic is wrapped in a lambda and passed to a static class that will execute the logic once for each row of test data when it is first called (first row executed). Successive calls to the static class simply wait for the prestarted test Task to finish.
In this way each call the test framework made to the TestMethod simply collects the test results of the corresponding test that was already run.
Possible Improvements: