Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Test fixture inheritance and ignored base test fixtures

Tags:

nunit

I have a set of base tests that are used to test multiple implementations of a interface. The way I modelelled this was by creating a base text fixture with a [Ignore] attribute.

[TestFixture]
[Ignore]
public class BaseTests
{
     // Use your imagination for the actual name
     public virtual ITestableThing GetConcrete()
     {
         return null;
     }

     // All of my unit tests here
}

And then I write a subclass for each interface implementation:

public class ConcreteThingTests :  BaseTests
{
    public override ITestableThing GetConcrete()
    {
        return new ConcreteThing();
    }
}

This works well, as I have all of the tests for ALL implementations in one place, and the sub classes just specify the implementation.

The problem is that I have to put the [Ignore] attribute on the base class, or NUnit will try to run the tests (and fail).

Because of this, my test results are always cluttered up with a set of Ignored tests, and while it's not a big deal, I thought there might be a better pattern for this that avoids having to ignore tests.

So, am I implementing test fixture inheritance wrong?

like image 639
Jonathan Holland Avatar asked Aug 03 '13 14:08

Jonathan Holland


People also ask

What is the purpose of test fixture?

The main advantage of a test fixture is that it allows for tests to be repeatable since each test is always starting with the same setup. Test fixtures also ease test code design by allowing the developer to separate methods into different functions and reuse each function for other tests.

What is test fixture in unit test?

A test fixture (also known as a test context) is the set of preconditions or state needed to run a test. The developer should set up a known good state before the tests, and return to the original state after the tests. Wikipedia (xUnit)

What is test fixture in selenium?

In software development, test fixtures (fixtures) is a term used to describe any test data that lives outside of that particular test, and is used to set the application to a known fixed state.

What is a test fixture class?

A Test Fixture is the class that contain the tests we want to run. We typically write one test fixture for each class we want to test. As a convention we name the test fixture <Class to be tested>Tests. cs. e.g. test fixture for Simple.


2 Answers

The NUnit test runner appears to ignore the base class if it is marked abstract:

public abstract class BaseTests
{
}
like image 85
Lee Avatar answered Dec 26 '22 22:12

Lee


You would normally set the test attributes on your concrete test classes, not the base class.

Since you seem to test the same functionality for multiple classes, you could skip the whole test hierarchy and inject the concrete classes to be tested to that test-baseclass.

To do that with NUnit you could use the TestCaseSource attribute with a class factory method as a parameter. An example of that can be found here: How to pass dynamic objects into an NUnit TestCase function?

Making up some code for your particular case, it could be like shown below:

/// <summary>
/// Earlier known as your BaseTests class
/// </summary>
[TestFixture]
public class TestOfConcreteImplementationsOfInterface
{
    [TestCaseSource("CreateConcretes")]
    [Test]
    public void VerifyImplementations(IWhatever thing)
    {
        int input = 42;
        int result = thing.DoSomething(input);
        Assert.That(result, Is.EqualTo(input));
    }

    /// <summary>
    /// Factory method for the concrete classes.  If you want this in a seperate class, you can do that too using the 
    /// ctor public TestCaseSourceAttribute(Type sourceType, string sourceName);
    /// </summary>
    public IEnumerable<IWhatever> CreateConcretes
    {
        get
        {
            yield return new A();
            yield return new B();
        }
    }
}

public interface IWhatever
{
    int DoSomething(int x);
}

public class A : IWhatever
{
    public int DoSomething(int x)
    {
        return x;
    }
}

public class B : IWhatever
{

    public int DoSomething(int x)
    {
        return x;
    }
}
like image 36
Terje Sandstrøm Avatar answered Dec 26 '22 21:12

Terje Sandstrøm