Search code examples
c#unit-testingnunitnunit-3.0

Is there a way to repeat a nUnit TestFixture multiple times?


Is there a way to run a nunit TestFixture once for each item in a list? Let's say I have a setup something like the following:

Public Class TestData
{
Public String Parameter1{get;}
Public String Parameter2{get;}
Public String Parameter3{Get;}
}

What I would like to do is create a list of TestData objects:

List<TestData> inputs = new List<TestData>(){};

And then using nunit 3, run a TestFixture and all Tests housed within it against each item in the list.


Solution

  • The TestFixtureAttribute may take a list of arguments, similar to the TestCaseAttribute. The values provided are used as arguments to the constructor of the test class. The usual process is to save the constructor arguments in a member variable. For example:

    [TestFixture(123, "John")]
    [TestFixture(456, "Mary")]
    [TestFixture(789, "Fred")]
    public class MyTest
    {
        private int _num;
        private string _name;
    
        public MyTest(int num, string name)
        {
            _num = num;
            _name = name;
        }
    
        ...
    }
    

    The fixture will be created and executed three times, once for each set of arguments. You may use the saved values in your tests, which may be simple tests or parameterized tests.

    As with [TestCase], you are limited to constant arguments of the types permitted by the C# languge.

    If you don't like that limitation and/or have a lot of test cases and prefer to consolidate the data, you can replace all the [TestFixture] entries by a single [TestFixtureSource], like this...

    [TestFixtureSource(nameof(MyTestData))]
    public class MyTest
    {
        private int _num;
        private string _name;
    
        public MyTest(int num, string name)
        {
            _num = num;
            _name = name;
        }
    
        ...
    
        static IEnumerable<TestFixtureData> MyTestData()
        {
            yield return new TestFixtureData(123, "John");
            yield return new TestFixtureData(456, "Mary");
            yield return new TestFixtureData(789, "Fred");
        }
    }
    

    This attribute is a bit more complicated than [TestCase] so be sure to read the documentation. In particular, check out "Form 2" if you want to share the same data among multiple fixture classes.