Using the 'TestCase' attribute with a two-dimensional array

4.5k Views Asked by At

I'm using NUnit and trying to implement tests for the following method: It should accept two integers and returns two dimensional array. So, header of my test looks like:

[TestCase(5, 1, new int[,]{{1}, {2}, {3}, {4}, {5}})]
public void MyTestMethod(int a, int b, int[][] r)

During compilation I've got the following error:

Error CS0182: An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type (CS0182)


I know it can be done using TestCaseSource to refer to object arrays like the answers to the following questions:

which gives code like:

private object[][] combination_tests =  new [] {
    new object[] {5, 1, new [,]{{1}, {2}, {3}, {4}, {5}}},
};

[Test]
[TestCaseSource("combination_tests")]
public void MyTestMethod(int a, int b, int[,] r)

but I still have the question: is it possible to do that with using only the TestCase attribute?

2

There are 2 best solutions below

0
On

You can use the TestCaseData object to pass the results in:

public IEnumerable<TestCaseData> combination_tests()
{
    yield return new TestCaseData(5,1,new int[,] {{1}, {2}, {3}, {4}, {5}});
}

[Test]
[TestCaseSource("combination_tests")]
public void test(int a, int b, int[,] r)
{
    Console.WriteLine(r[0,0] & r[1,0]);
}

You can also set the test category and test name for each testCaseData item using .SetName("xxx") or .SetCategory("xxx") which can be nice for organizing the tests.

0
On

Is it absolutely necessary for you to have the same signature for your method, i.e.

public void MyTestMethod(int a, int b, int[][] r)
{
    // elided
}

Depending on your situation, you have two options available, both of which use the [TestCase] attribute as you said you wanted in the question:

is it possible to do that with using only the TestCase attribute?

I prefer the first option as it feels more concise, but both will suit your needs.


Option 1: If it is NOT necessary to keep the same signature

You could modify the signature slightly so that instead of an array (not compile-time constant), you pass in a string (which is compile-time constant) which can be used to obtain the array instead, e.g.

private static int[][] getArrayForMyTestMethod(string key)
{
    // logic to get from key to int[][]
}

[TestCase(5, 1, "dataset1")]
public void MyTestMethod(int a, int b, string rKey)
{
    int[][] r = getArrayForMyTestMethod(rKey);
    // elided
}

Option 2: If it IS necessary to keep the same signature

If it is necessary to keep the same signature for the method, you could have a wrapper method that does the same as option 1, i.e.

private static int[][] getArrayForMyTestMethod(string key)
{
    // logic to get from key to int[][]
}

[TestCase(5, 1, "dataset1")]
public void MyTestMethodWrapper(int a, int b, string rKey)
{
    int[][] r = getArrayForMyTestMethod(rKey);
    MyTestMethod(a, b, r);
}

public void MyTestMethod(int a, int b, int[][] r)
{
    // elided
}

Obviously you could use any type which can be compile-time constant instead of a string depending on the way your test cases are constructed, but I suggested a string because you'd be able to give a name to your test case in the NUnit runner that way.


Otherwise your alternative is to use [TestCaseSource] as you mentioned in your question.