Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to run ClassCleanup (MSTest) after each class with test?

Tags:

I have several classes with tests suites.

Each test class starts from ClassInitialize and finishes by ClassCleanup. My problem is that ClassCleanup isn't called at the end of each class, it's called only after all tests in three classes. Can I fix this issue? Thanks!

[ClassInitialize] public static void SetUpBrowser(TestContext context) {     pageObjectBase.SetBrowser("chrome");     pagesManager.GetPageObjectBase(); }  [TestMethod] public void FindCriticalBug() {     bla-bla-bla(); }  [ClassCleanup] public static void CloseBrowser() {     pageObjectBase.Stop();     pagesManager.GeneralClearing(); } 
like image 865
Ellina Avatar asked Jun 09 '14 09:06

Ellina


People also ask

Does TestInitialize run for each test?

TestInitialize and TestCleanup are ran before and after each test, this is to ensure that no tests are coupled. If you want to run methods before and after ALL tests, decorate relevant methods with the ClassInitialize and ClassCleanup attributes.

Which attribute is used on a method to run once after all tests have run in an assembly?

The method decorated by [AssemblyInitialize] is called once before running the tests of the assembly. The method decorated by [AssemblyCleanup] is called after all tests of the assembly are executed. These methods can be located in any class as long as the class is decorated by [TestClass] .

Which attribute should be used to mark a method as test method in MSTest testing?

The TestClass attribute denotes a class that contains unit tests. The TestMethod attribute indicates a method is a test method.


2 Answers

Tests are run unordered, including tests across classes. See this blog post:

https://docs.microsoft.com/archive/blogs/ploeh/classcleanup-may-run-later-than-you-think

To quote:

In any case, here's the result from my Output Window:

AssemblyInitialize TestClass1: ClassInitialize TestClass1: TestInitialize TestClass1: MyTestCase1 TestClass1: TestCleanup TestClass2: ClassInitialize TestClass2: TestInitialize TestClass2: MyTestCase2 TestClass2: TestCleanup TestClass1: ClassCleanup TestClass2: ClassCleanup AssemblyCleanup 

...this doesn't mean that TestClass1's ClassCleanup executes immediately after the last test case in the class! In fact, it waits until all test cases are executed, and the executes together with TestClass2's ClassCleanup.

This surprised me at first, but that was obviously only because I hadn't really thought it through: Since tests are, in principle, unordered, there's not guarantee that all tests in TestClass1 are executed in immediate succession. Theoretically, the execution engine may pick a test case from TestClass1, then one from TestClass2, then another from TestClass1, etc. Since that is the case, there's no guarantee that all tests from one test class have been executed before a new test class is initialized, and thusly, all ClassCleanup methods may as well be deferred until all test cases have been executed.

Unfortunately, you'll have to look at ordered tests or at a different unit testing framework if this doesn't work for you.

like image 89
John Koerner Avatar answered Oct 21 '22 01:10

John Koerner


There is a different attribute called TestCleanupAttribute, which will run after every test.

There is also an attribute to run before every test called TestInitializeAttribute.

Here is an example of them running together.

[TestClass] public class MyTests {    [ClassInitialize]    public void ClassInitialize() { Debug.Print("Running ClassInitialize"); }     [TestInitialize]    public void TestInitialize() { Debug.Print("Running    TestInitialize"); }     [TestMethod]    public void TestMethod1() { Debug.Print("Running       TestMethod1....."); }     [TestMethod]    public void TestMethod2() { Debug.Print("Running       TestMethod2....."); }     [TestCleanup]    public void TestCleanup() { Debug.Print("Running    TestCleanup"); }     [ClassCleanup]    public void ClassCleanup() { Debug.Print("Running ClassCleanup"); } } 

This will result in

Running ClassInitialize Running    TestInitialize Running       TestMethod1..... Running    TestCleanup Running    TestInitialize Running       TestMethod2..... Running    TestCleanup Running ClassCleanup 
like image 23
Dominic Zukiewicz Avatar answered Oct 21 '22 02:10

Dominic Zukiewicz