danielwertheim

danielwertheim


notes from a passionate developer

Developer that lives by the mantra "code is meant to be shared".

Share


Tags


Disclaimer

This is a personal blog. The opinions expressed here represent my own and not those of my employer, nor current or previous. All content is published "as is", without warranty of any kind and I don't take any responsibility and can't be liable for any claims, damages or other liabilities that might be caused by the content.

NUnit call chain and sample usage

Daniel WertheimDaniel Wertheim

Been using xUnit for a long time now, and thought it was about time to revisit NUnit again, now that it is out in v3.0. Taking a step “back”. Back to the possibility of being able to use attributes for setup and teardown again. Being able to easily have assembly initialization. And do you know what? I LIKE IT! I like having simple attributes for assembly initialization. I like having attributes that enable me to control setup- and tear down behaviour. Of course, there’s also the option of using the constructor and/or IDisposable for those who want. So, with this said. Lets just have a quick peek at what point each construct “kicks in”, in the execution of one or more tests. Lets also look at a simple base class construct that can be used to hide the attributes away and possibly providing more semantic names.

How does the call chain look?

Lets start with the possibility of having assembly initialization and tear down by using SetupFixtureAttribute and IDisposable:

[SetUpFixture]
public class TestingAssembly : IDisposable  
{
    public TestingAssembly() {
        WriteLine("In cTor");
    }

    public void Dispose() {
        WriteLine("In Dispose");
    }

    static void WriteLine(string value)
    {
        File.AppendAllText(
            @"D:Tempdump.txt",
            "TestingAssembly|" + value + Environment.NewLine);
    }
}

And in a “test-class”, you can make use the constructor and IDisposable as well as the attributes: SetupAttribute, OneTimeSetup, TearDown and OneTimeTearDown:

public class Testing1 : IDisposable  
{
    public Testing1()
    {
        WriteLine("In cTor");
    }

    public void Dispose()
    {
        WriteLine("In Dispose");
    }

    [SetUp]
    public void Foo1()
    {
        WriteLine("In SetUp");
    }

    [OneTimeSetUp]
    public void Foo2()
    {
        WriteLine("OneTimeSetUp");
    }

    [OneTimeTearDown]
    public void Foo3()
    {
        WriteLine("OneTimeTearDown");
    }

    [TearDown]
    public void Foo4()
    {
        WriteLine("In TearDown");
    }

    [Test]
    public void Test1()
    {
        WriteLine("In test1");
    }

    [Test]
    public void Test2()
    {
        WriteLine("In test2");
    }

    static void WriteLine(string value)
    {
        File.AppendAllText(
            @"D:Tempdump.txt",
            "Testing1|" + value + Environment.NewLine);
    }
}
public class Testing2 : IDisposable  
{
    public Testing2()
    {
        WriteLine("In cTor");
    }

    public void Dispose()
    {
        WriteLine("In Dispose");
    }

    [SetUp]
    public void Foo1()
    {
        WriteLine("In SetUp");
    }

    [OneTimeSetUp]
    public void Foo2()
    {
        WriteLine("OneTimeSetUp");
    }

    [OneTimeTearDown]
    public void Foo3()
    {
        WriteLine("OneTimeTearDown");
    }

    [TearDown]
    public void Foo4()
    {
        WriteLine("In TearDown");
    }

    [Test]
    public void Test1()
    {
        WriteLine("In test1");
    }

    [Test]
    public void Test2()
    {
        WriteLine("In test2");
    }

    static void WriteLine(string value)
    {
        File.AppendAllText(
            @"D:Tempdump.txt",
            "Testing2|" + value + Environment.NewLine);
    }
}

Result

The output of the above would be:

TestingAssembly|In cTor  
Testing1|In cTor  
Testing1|OneTimeSetUp  
Testing1|In SetUp  
Testing1|In test1  
Testing1|In TearDown  
Testing1|In SetUp  
Testing1|In test2  
Testing1|In TearDown  
Testing1|OneTimeTearDown  
Testing1|In Dispose  
Testing2|In cTor  
Testing2|OneTimeSetUp  
Testing2|In SetUp  
Testing2|In test1  
Testing2|In TearDown  
Testing2|In SetUp  
Testing2|In test2  
Testing2|In TearDown  
Testing2|OneTimeTearDown  
Testing2|In Dispose  
TestingAssembly|In Dispose  

Avoiding confusion

Most often, I actually do hide the usage of the attributes, by using a base-class, providing somewhat more semantic names (I think). That could be something like this:

public abstract class UnitTests  
{
    [SetUp]
    [DebuggerStepThrough]
    protected virtual void OnBeforeEachTest() { }

    [TearDown]
    [DebuggerStepThrough]
    protected virtual void OnAfterEachTest() { }

    [OneTimeSetUp]
    [DebuggerStepThrough]
    protected virtual void OnBeforeAllTests() { }

    [OneTimeTearDown]
    [DebuggerStepThrough]
    protected virtual void OnAfterAllTests() { }
}

Summary

Mostly a post for myself to go somewhere when I need to remember. If useful for you as well, then…sweet.

Cheers,

//Daniel

Developer that lives by the mantra "code is meant to be shared".

Comments