LN.EXE
LN.EXE

Reputation: 59

NUnit: TestCaseSource assigns tests to specific test methods

I'm planning to store all test cases in a excel file with columns indicate test method names, parameters and expected results; however, I found TestCaseSource simply assigns all test cases to every test method. I'm wondering that is there any way I can make NUnit select test cases for methods base on method names I put in the spreadsheet?

Thanks.

Upvotes: 2

Views: 1549

Answers (2)

Kote
Kote

Reputation: 2256

There is a way to do this. For example, as you mentioned, you can create a custom attribute.
The idea is to pass name of test to TestCaseSource.
You can do it by creating TestCaseSource as separate class.

First, TestCaseSource class:

public class SpreadSheetTestCaseSource
{
    [ThreadStatic] 
    public static string TestName = String.Empty;

    public static IEnumerable TestCases
    {
        get
        {
            SpreadSheetTestCaseProvider.GetTestCases()
                 .Where(testCase => testCase.TestName == TestName);
        }
    }
}

Then attribute:

public class MyTestCaseSourceAttribute : TestCaseSourceAttribute
{
    public MyTestCaseSourceAttribute(Type sourceType, string sourceName, 
        [CallerMemberName] string name = null)
        : base(sourceType, sourceName)
    {
        SpreadSheetTestCaseSource.TestName = name;
    }

    //Another two members impl.
}

And test:

[TestFixture]
public class TestClass
{
    [MyTestCaseSource(typeof(SpreadSheetTestCaseSource), "TestCases")]
    public void TestMethod()
    {
        //Test logic
    }
}

SpeadSheetTestCaseSource.TestName is thread static. So you can run tests parallel.

Upvotes: 1

Rob Prouse
Rob Prouse

Reputation: 22647

This isn't a feature that NUnit supports directly. The various TestCaseSource type attributes have no ability to feed a test method based on the input.

An option would be to create a TestCaseSource for each of your test methods. Each of these would be a simple wrapper that passes in the method name to a single internal method. That internal method would read in the Excel file and only return the rows for the given method name.

PseudoCode;

[TestCaseSource(nameof(TestMethodOneSource))]
public void TestMethodOne(int x, int y, int expected)
{
   Assert.That(x + y, Is.EqualTo(expected));
}

public static IEnumerable<object[]> TestMethodOneSource() =>
    ReadExcel(nameof(TestMethodOne));

private static  IEnumerable<object[]> ReadExcel(string method)
{
    // Open and start reading Excel
    for(var row in rows)
    {
        if(row[0] == method)
        {
            // Return objects minus the method
            yield return new [] {row[1], ..., row[n]};
        }
    }
 }

Upvotes: 0

Related Questions