How to run unit tests (MSTest) in parallel?

前端 未结 6 2049
独厮守ぢ
独厮守ぢ 2020-11-29 02:19

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

6条回答
  •  野性不改
    2020-11-29 02:57

    1. Ensure the first column in your DataTable is a unique Id.
    2. Create a AsyncExecutionTask delegate that accepts a DataRow and returns nothing.
    3. Create a static class (ParallelTesting) with a AsyncExecutionContext method that accepts a DataRow and an AsyncExecutionTask delegate.
    4. In the static class add a static BatchStarted property.
    5. In the static class add a static AsyncExecutionTests Dictionary property.
    6. 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;
      }
      
    7. 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:

    • Make AsyncExecutionContext take a maxSynchronousTasks parameter.
    • Look into how the framework moves complete stacktraces across unmanaged code to see if the Task.Exception can be passed to the visual studio test framework without rethrowing and destroying the stacktrace.

提交回复
热议问题