views:

290

answers:

5

Hi,

I have an issue with NUnit - wondering if anyone has any ideas.

We're using NUnit 2.5.3.9345 and C# 3.5.

Take the following code:

public class UnitTestBase
{
    [TestFixtureSetUp]
    public void SetUpTestFixture()
    {
        //Do something in base
    }
}

[TestFixture]
public class SomeTestClass : UnitTestBase
{
    [TestFixtureSetUp]
    public void FixtureSetUp()
    {
        //Do something in test class
    }

    [Test]
    public void SomeTest()
    {
        //Some assertion
    }
}

According to the documentation, if I run SomeTestClass.SomeTest(), UnitTestBase.SetUpTestFixture() should be called before SomeTestClass.FixtureSetUp().

This isn't the case - the base method will only be called if I don't provide a [TestFixtureSetUp] method in the derived class.

Any ideas please? Has me really puzzled!

Thanks.

A: 

Have you tried giving the base class the [TestFixture] attribute? I don't know that that will fix it, but it seems like it might be worth a try... the idea is that NUnit may be ignoring the attributes on the base class if it's not a TestFixture.

McWafflestix
Yeah same behaviour with our without [TestFixture] on the base class.If I take the [TestFixtureSetUp] attribute off the derived class method, then the base is called.
Michael
A: 

Yep, I've been playing around with this for past half hour and it's definitely a bug. I've tried adding TestFixture to all classes as well as having different combinations. I've also tried static and instance methods. It just doesn't seem to want to play nicely! :-(

Anyway, the best workaround I could find is to put the TestFixtureSetUp code in the constructors of your test class and base class. At least then you can be confident of the inheritance and it's more clear to other readers of your code who maybe don't know the inner workings of NUnit :-)

Russell Giddings
By the way, I tried it against NUnit v2.5.0.9122 and it doesn't work with this version either so this is not something that has been introduced recently.
Russell Giddings
Tried it in the NUnit Windows App and using the Resharper runner, neither worked. :-(
Russell Giddings
I just ran the exact code from Marks answer and it only output the derived classes test output, nothing from the base class. I'm starting to clutch at straws now but I've just noticed that he was running 32-bit. I'm running 64-bit. Could this be the difference thats causing differing outcomes?
Russell Giddings
@Russell, maybe you could try building in x86 and trying the nunit-x86 gui runner to see if the 64bit version is causing issues.
Mark
Nope, just tried it on a 32-bit machine and had the same issue. :-(
Russell Giddings
A: 

A workaround / different way of doing it:

Instead of relying on behaviour that is not immediately clear, do something like this instead using the template method pattern to make the ordering explicit using normal language features:

public class UnitTestBase
{
    protected abstract void PerFixtureSetUp();

    [TestFixtureSetUp]
    public void SetUpTestFixture()
    {
        PerFixtureSetUp();
    }
}

[TestFixture]
public class SomeTestClass : UnitTestBase
{
    protected override void PerFixtureSetUp()
    {

    }

    [Test]
    public void SomeTest()
    {
        //Some assertion
    }
}

Any time I have had reason to use inherited fixtures or test contexts, this way has worked well enough. :)

My problem with relying on the attributes is that since these types are created and invoked via reflection in the runner with no relation between the methods, (no polymorphism) it's harder to reason about the order in which they're called. Using standard language features helps simplify this a little.

Mark Simpson
I do think this is a good way to approach the situation yes - I just quite fancy using the built-in features of NUnit.The ordering isn't too much of an issue, as long as I only define one of each method in the base and one of each in the derived class - that way there's some guarantee of the ordering (provided no exceptions are thrown during setup / teardown)
Michael
+2  A: 

I am not having the problem. I tested the outcome with the following:

Derived Test

[TestFixture]
public class DerivedTest : TestBase
{

    [TestFixtureSetUp]
    public void FixtureSetup()
    {

        File.AppendAllText("Out.txt", string.Format("TestFixtureSetUp From DerivedTest{0}", Environment.NewLine));
    }

    [TestFixtureTearDown]
    public void FixtureTearDown()
    {
        File.AppendAllText("Out.txt", string.Format("TestFixtureTearDown Down From DerivedTest{0}", Environment.NewLine));
    }

    [SetUp]
    public void Setup()
    {
        File.AppendAllText("Out.txt", string.Format("Setup From DerivedTest{0}", Environment.NewLine));
    }
    [TearDown]
    public void Down()
    {
        File.AppendAllText("Out.txt", string.Format("TearDown From DerivedTest{0}", Environment.NewLine));
    }

    [Test]
    public void DoATest()
    {
        File.AppendAllText("Out.txt", string.Format("Did a Test{0}", Environment.NewLine));
    }
}

TestBase

public class TestBase
{

    [TestFixtureSetUp]
    public void BaseTestFixtureSetUp()
    {
        File.AppendAllText("Out.txt", string.Format("TestFixtureSetUp From TestBase{0}", Environment.NewLine));
    }

    [TestFixtureTearDown]
    public void BaseTestFixtureTearDown()
    {
        File.AppendAllText("Out.txt", string.Format("TestFixtureTearDown From TestBase{0}", Environment.NewLine));
    }

    [SetUp]
    public void BaseSetup()
    {
        File.AppendAllText("Out.txt", string.Format("Setup From TestBase{0}", Environment.NewLine));
    }

    [TearDown]
    public void TearDown()
    {
        File.AppendAllText("Out.txt", string.Format("TearDown From TestBase{0}", Environment.NewLine));
    }
}

This produces the following output:

TestFixtureSetUp From TestBase
TestFixtureSetUp From DerivedTest
Setup From TestBase
Setup From DerivedTest
Did a Test
TearDown From DerivedTest
TearDown From TestBase
TestFixtureTearDown Down From DerivedTest
TestFixtureTearDown From TestBase

I am was able to test the output with ReSharper 5 beta and the Nunit GUI v 2.5.3.9345 (32-bit)

Edit While at work the test runner in ReSharper 4.5 did not work properly, however running the built test project in x86 and x64 with the corresponding NUnit.exe/NUnit-86.exe produced valid output.

Mark
Were you using ReSharper 5 by any chance?
Michael
Yes I am using beta 5 at home.
Mark
Michael
A: 

What are you running your tests with? The behavior you are experiencing is not related to NUnit (framework), rather the runner you are using. Are you using Resharper integrated testrunner?

Simone
I've tried both the NUnit GUI and the Resharper runner with the same outcome.
Russell Giddings
Does that change anything if you put a TestFixtureTearDown either on the base or the derived or both?
Simone
Seems that using the NUnit 2.5.3 GUI this works and ReSharper 5 beta 2 works.ReSharper 4.5.1 seems to be the issue, along with our build of TeamCity (5.0.10669)
Michael