Friday 18 July 2014

Using TDD, how I found that NUnit TestFixtureSetUp and TestFixtureTearDown (from base classes) are not called when a Constructor exists (in the main class)

Just hit an interesting issue which I'm sure there is a good explanation for, but It caught me off guard.

I was working on this NUnit test called Test_Tbot_User_View


... which extends the TestFixture_TBot class


... which simplifies the use of the FluentSharp.Watin's API_IE_TBot (see code here)

The problem happened when I decided to use the NUnit's TestFixtureSetUp and TestFixtureTearDown attributes to create special methods that are executed on TestFixture beginning and ending.

To do so, I refactored the TestFixture_TBot class to:


Then (in a couple seconds), I started to get an NCrunch error on an NUnit test that was working before (those couple seconds were the time it took NCrunch to re-run the affected NUnit test)


As you can see on the screenshot above, the error was happening on the Test_Tbot_User_View constructor, with no code executed on the main page__User_View() test method (the black dots represent code that was not covered (courtesy of NCrunch real-time code-coverage mappings)

A quick look at the testFixtureSetUp method, also confirms that it was not executed:


Next, I commented out the Conductor of the Test_Tbot_User_View class, and after a couple of NCrunch seconds, the test was now executed and failing in a location I would expect it to (since that TBot page needs to be accessed by an admin user, the ie.url() is returning the TeamMentor login page url)


Looking at TestFixture_TBot confirms that both methods marked with TestFixtureSetUp and TestFixtureTearDown attributes where triggered by NUnit (the reason the have red dots is because that is how NCrunch represents code paths that where executed OK, but there was a failure in of the UnitTests that used them)


After a bit of research and tests, I found that the solution was to remove the constructor from Test_Tbot_User_View, and add the tbot.login_As_Admin() call to the page__User_View() method:


... or to add a method decorated with the SetUp attribute (which will be called before each test executes)


Note that these tests are running in a full (clean) IE instance, created just for this test. To see it in action, I can just add the ie.parentForm().show().waitForClose(); at the end of the UnitTest, and see the end result:


 In terms of performance, as you can see below, the entire test (from creating the Window Form with the embedded IE, logging in and opening up the admin page) takes less than 2 secs (and 1:085 of it was creating the target IE instance)