开发者

Forcing MSTest to use a single thread

开发者 https://www.devze.com 2023-02-12 00:30 出处:网络
Given this test fixture: [TestClass] public class MSTestThreads { [TestMethod] public void Test1() { Trace.WriteLine(Thread.CurrentThread.ManagedThreadId);

Given this test fixture:

[TestClass]
public class MSTestThreads
{
    [TestMethod]
    public void Test1()
    {
        Trace.WriteLine(Thread.CurrentThread.ManagedThreadId);
    }

    [TestMethod]
    public void Test2()
    {
        Trace.WriteLine(Thread.CurrentThread.ManagedThread开发者_如何学GoId);
    }
}

Running the test with MSTest through Visual Studio or command line prints two different thread numbers (yet they are run sequentially anyway).

Is there a way to force MSTest to run them using a single thread?


I solved this problem with locking:

public static class IntegrationTestsSynchronization
{
    public static readonly object LockObject = new object();
}

[TestClass]
public class ATestCaseClass
{
    [TestInitialize]
    public void TestInitialize()
    {
        Monitor.Enter(IntegrationTestsSynchronization.LockObject);
    }

    [TestCleanup]
    public void TestCleanup()
    {
        Monitor.Exit(IntegrationTestsSynchronization.LockObject);
    }

    //test methods
}

// possibly other test cases

This can of course be extracted to a base test class and reused.


I've fought for endless hours to make MSTest run in a single threaded mode on a large project that made heavy use of nHibernate and it's not-thread-safe (not a problem, it's just not) ISession.

We ended up more time writing code to support the multi-threaded nature of MSTest because - to the best of my and my teams knowledge - it is not possible to run MSTest in a single threaded mode.


You can derive your test class from

public class LinearTest
{
    private static readonly object SyncRoot = new object();

    [TestInitialize]
    public void Initialize()
    {
        Monitor.Enter(SyncRoot);
    }

    [TestCleanup]
    public void Cleanup()
    {
        Monitor.Exit(SyncRoot);
    }
}


We try hard to make out tests isolated from each other. Many of them achieve this by setting up the state of a database, then restoring it afterwards. Although mostly tests set up different data, with some 10,000 in a run there is a fair chance of a collision unless the code author of a test takes care to ensure its initial data is unique (ie doesn't use the same primary keys as another test doing something similar). This is, frankly, unmanageable, and we do get occasional test failures that pass second time around. I am fairly sure this is caused by collisions that would be avoided running tests strictly sequentially.


The way to make an MSTest method run in single-threaded mode:

Nuget:

install-package MSTest.TestAdapter
install-package MSTest.TestFramework

In your test source on those methods that need to run while no other tests are running:

[TestMethod]
[DoNotParallelize]
public void myTest(){
    //
}


Whilst it is a cop out answer, I would actually encourage you to make your code thread-safe. The behaviour of MSTest is to ensure isolation as Richard has pointed out. By encountering problems with your unit tests you are proving that there could be some problems in the future.

You could ignore them, use NUnit, or deal with them and continue to use MSTest.


I tried a bit of a different approach, because the underlying problem is that the names of the pipes are the problem. So I made a fakePipe, derived it from the one I use in the program. And named the pipe with the tests name.

[TestClass]
public class PipeCommunicationContractTests {
  private PipeDummy pipe;

  /// <summary>
  ///Gets or sets the test context which provides
  ///information about and functionality for the current test run.
  ///</summary>
  public TestContext TestContext { get; set; }

  [TestInitialize]
  public void TestInitialize() {
     pipe = new PipeDummy(TestContext.TestName);
     pipe.Start();
  }

  [TestCleanup]
  public void TestCleanup() {
  {
     pipe.Stop();
     pipe = null;
  }
   ...
  [TestMethod]
  public void CallXxOnPipeExpectResult(){
      var result = pipe.Xx();
      Assert.AreEqual("Result",result); 
  }
}

It appears to be a bit faster, since we can run on multiple cores and threads...

0

精彩评论

暂无评论...
验证码 换一张
取 消