Welcome to MSDN Blogs Sign in | Join | Help

That Pesky MSTest Execution Ordering..

I have come upon several groups who are puzzled by the intricacies of execution of the MSTest Framework.  I admit - it is quite confusing, so I hope that these postings will help to clean some of the confusion.

I think that most confusion comes from some user’s expectation of MSTest to execute like the Nunit framework.  They execute differently since Nunit instantiates a test class only once when executing all the tests contained in it, whereas MSTest instantiates each test method’s class separately during the execution process, with each instantiation occurring on a separate thread. This design affects 3 specific things which often confuse users of MSTest:

1.      ClassInitialize and ClassCleanup: Since ClassInitialize and ClassCleanUp are static, they are only executed once even though several instances of a test class can be created by MSTest.  ClassInitialize executes in the instance of the test class corresponding to the first test method in the test class. Similarly, MSTest executes ClassCleanUp in the instance of the test class corresponding to the last test method in the test class.

2.      Execution Interleaving: Since each instance of the test class is instantiated separately on a different thread, there are no guarantees regarding the order of execution of unit tests in a single class, or across classes. The execution of tests may be interleaved across classes, and potentially even assemblies, depending on how you chose to execute your tests. The key thing here is – all tests could be executed in any order, it is totally undefined.

3.      TextContext Instances: TestContexts are different for each test method, with no sharing between test methods.

 

For example, if we have a Test Class:

    [TestClass]

    public class VSTSClass1

    {

      

        private TestContext testContextInstance;

 

        public TestContext TestContext

        {

            get

            {

                return testContextInstance;

            }

            set

            {

                testContextInstance = value;

            }

        }

 

 [ClassInitialize]

        public static void ClassSetup(TestContext a)

        {

            Console.WriteLine("Class Setup");

        }

 

        [TestInitialize]

        public void TestInit()

        {

            Console.WriteLine("Test Init");

 

        }

 

        [TestMethod]

        public void Test1()

        {

            Console.WriteLine("Test1");

        }

 

        [TestMethod]

        public void Test2()

        {

            Console.WriteLine("Test2");

 

        }

 

        [TestMethod]

        public void Test3()

        {

            Console.WriteLine("Test3");

        }

 

        [TestCleanup]

        public void TestCleanUp()

        {

            Console.WriteLine("TestCleanUp");

        }

 

        [ClassCleanup]

        public static void ClassCleanUp()

        {

            Console.WriteLine("ClassCleanUp");

        }

    }

(This consists of 3 Test Methods, ClassInitialize, ClassCleanup, TestInitialize, TestCleanUp and anexplicit declaration of TestContext)

The execution order would be as follows:

Test1 [Thread 1]: new TestContext -> ClassInitialize -> TestInitialize -> TestMethod1 ->  TestCleanUp

Test2 [Thread 2]: new TestContext -> TestInitialize -> TestMethod2 ->  TestCleanUp

Test3 [Thread 3]: new TestContext -> TestInitialize -> TestMethod2 ->  TestCleanUp -> ClassCleanUp

The output after running all the tests in the class would be:

Class Setup

Test Init

Test1

TestCleanUp

Test Init

Test2

TestCleanUp

Test Init

Test3

TestCleanUp

ClassCleanUp

 (A special thanks to Dominic Hopton for his edits of my hackery on this post :))

Published Saturday, February 17, 2007 1:41 AM by nnaderi

Comments

# Matriz de atributos MSTest versus NUnit

Naderi é PM (Program Manager) do VSTS Test Team e escrever bastante sobre testes unitários utilizando

Sunday, April 01, 2007 6:50 PM by Console.Write(this.Opinion)

# re: That Pesky MSTest Execution Ordering..

Running more than one test at the same time is great.

But are you planning a mode to define a special order of execution ? (Test dependency)

Wednesday, July 18, 2007 10:41 PM by FredericALTorres

# re: That Pesky MSTest Execution Ordering..

I extended the test a little bit to see how MSTest behaves with VS2005 and multiple test classes in different test projects. I also added code to print on what thread the methods get called.

This is what I see when I run the tests from the Test View (please note the nice typo :)

---------------

Class Setup 1 (on thread AdpaterExeMgrThread1)

Test Init 1 (on thread AdpaterExeMgrThread1)

Test 1.1 (on thread AdpaterExeMgrThread1)

TestCleanUp 1 (on thread AdpaterExeMgrThread1)

Test Init 1 (on thread AdpaterExeMgrThread1)

Test 1.2 (on thread AdpaterExeMgrThread1)

TestCleanUp 1 (on thread AdpaterExeMgrThread1)

Test Init 1 (on thread AdpaterExeMgrThread1)

Test 1.3 (on thread AdpaterExeMgrThread1)

TestCleanUp 1 (on thread AdpaterExeMgrThread1)

Class Setup 2 (on thread AdpaterExeMgrThread1)

Test Init 2 (on thread AdpaterExeMgrThread1)

Test 2.1 (on thread AdpaterExeMgrThread1)

TestCleanUp 2 (on thread AdpaterExeMgrThread1)

Test Init 2 (on thread AdpaterExeMgrThread1)

Test 2.2 (on thread AdpaterExeMgrThread1)

TestCleanUp 2 (on thread AdpaterExeMgrThread1)

Test Init 2 (on thread AdpaterExeMgrThread1)

Test 2.3 (on thread AdpaterExeMgrThread1)

TestCleanUp 2 (on thread AdpaterExeMgrThread1)

ClassCleanUp 1 (on thread TestCasemanager::ExecutionThread)

ClassCleanUp 2 (on thread TestCasemanager::ExecutionThread)

---------------

So all tests are run on the same thread and only the cleanup routines are called from a different thread. The class clean up methods are postponed until all test methods from all test classes have been run, which in my opinion makes the class initialize / clean up methods pretty useless unless your unit tests are very cleanly isolated.

Monday, January 21, 2008 5:39 AM by jisotupa

# re: That Pesky MSTest Execution Ordering..

Hmm, it seems that MsTest just does not name the threads - using the ManagedThreadId property we see something else:

Class Setup 1 (on thread 17)

Test Init 1 (on thread 17)

Test1.1 (on thread 17)

TestCleanUp 1 (on thread 17)

Test Init 1 (on thread 19)

Test1.2 (on thread 19)

TestCleanUp 1 (on thread 19)

Test Init 1 (on thread 20)

Test1.3 (on thread 20)

TestCleanUp 1 (on thread 20)

Class Setup 2 (on thread 21)

Test Init 2 (on thread 21)

Test2.1 (on thread 21)

TestCleanUp 2 (on thread 21)

Test Init 2 (on thread 19)

Test2.2 (on thread 19)

TestCleanUp 2 (on thread 19)

Test Init 2 (on thread 17)

Test2.3 (on thread 17)

TestCleanUp 2 (on thread 17)

ClassCleanUp 1 (on thread 16)

ClassCleanUp 2 (on thread 16)

Monday, January 21, 2008 6:00 AM by jisotupa

# re: That Pesky MSTest Execution Ordering..

For me this issue/design is making MS Unit tests pretty much useless and might cause me to think about starting to use nUnit again. The whole purpose of especially TestInitialize and TestCleanup is to run as pairs BEFORE the next test executes. If you have any database setup that you later change in your test it could cause a problem with the next test. Therefore it is imparitive that each test runs one at a time and always wraps the intitialize/cleanup pairs.

The idea of having tests run at the same time on different threads is a dream that I don't think can be unless you have a simple app that doesn't have any advanced database setup. This is not the apps I at least tend to work on.

Saying that you should switch to ordered tests isn't a good idea either. Test driven development practices usually mandates that you have a unit test drive your entry point into the code you are developing/changing. Therefore you want to just go to the individual test you are currently working on and debug through it. With ordered tests you might have to go through a massive amount of tests before you even get there. Not a good idea.

Wednesday, April 23, 2008 10:40 AM by johanw

# Осторожно: порядок выполнения модульных (unit) тестов

Насколько я помню, в классике модульного тестирования принято, что порядок выполнения модульных тестов

Thursday, August 14, 2008 10:51 AM by Дмитрий Лапшин
Anonymous comments are disabled
 
Page view tracker