2

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.

LN.EXE
  • 59
  • 8
  • Do you want to use one `TestCaseSource` for different test methods, so that each test will run only special group of test cases, based on its names? – Kote Feb 02 '16 at 15:45
  • Yes! More precisely, I'll put TestCaseSource attribute on all test methods. – LN.EXE Feb 02 '16 at 15:59

2 Answers2

1

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.

Kote
  • 2,116
  • 1
  • 19
  • 20
  • A much cleaner implementation than my idea. +1 – Rob Prouse Feb 02 '16 at 22:11
  • Thank you very much for your reply. Just a question, how can I implement SpreadSheetTestCaseSource class. SpreadSheetTestCaseProvider is inherited from TestCaseProvider right? – LN.EXE Feb 03 '16 at 14:26
  • @LiuGarry, In this case `SpreadSheetTestCaseSource` is just a fictional class. You can implement it by many ways. I am just assuming that it parses excel document into `IEnumerable`. – Kote Feb 03 '16 at 15:19
  • @LiuGarry It is worth note that excel is not the simplest format. Excel document parsing is more complex than JSON or xml parsing. (It's just an example. I dont urge you to use this formats). – Kote Feb 03 '16 at 15:31
  • I used excel data as a database then parse into IEnumerable. Thank you very much. I'll try it for myself. – LN.EXE Feb 03 '16 at 15:39
  • So, there is no problem. One thing to note. This provider implementation shoud create test case list only once per `TestFixture` (if parsing takes time). – Kote Feb 03 '16 at 15:45
0

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]};
        }
    }
 }
Rob Prouse
  • 22,161
  • 4
  • 69
  • 89
  • Thank you very much. I have thought about that. The problem is that I will have a lot of test methods so I need to create wrapper for every single test method. I'm wondering that if there is a way to , perhaps, create custom attribute to achieve this. – LN.EXE Feb 02 '16 at 16:21