1

Based on this question about the correct usage of nUnit's TestCaseAttribute, I was wondering whether to specify the test case directly on the implementation or create test methods (as when using explicit Assert.AreEqual etc.).

In the following, I specified examples for both approaches and also listed potential arguments for and against both cases that I could think of.


Specifying the test on the implementation

public class Math
{
    [TestCase(1, 2, ExpectedResult = 3)]
    public int Add(int a, int b)
    {
        return a + b;
    }
}

Pros:

  • Less code to write
  • TestCase kind of works as documentation

Cons:

  • having to reference nunit.framework.dll in the implementation project

Creating a test method

public class Math
{
    public int Add(int a, int b)
    {
        return a + b;
    }
}

public class MathTest
{
    [TestCase(1, 2, ExpectedResult = 3)]
    public int AddTest(int a, int b)
    {
        return new Math().Test(a, b);
    }
}

Pros:

  • No need to reference nunit.framework.dll in the implementation project, only in the test project

  • Tests are clearly separated from the code they test

Cons:

  • Code duplication - the test method has exactly the same signature as the actual implementation etc.

  • more code to write

  • test doesn't work as a kind of documentation anymore


Are there any more arguments for or against either of the mentioned approaches?

What approach should I follow? (as in what approach is generally used, which is considered "Better Practice"?)

  • 2
    Wow. I never thought about using TestCase in production code like in the first case. IMO having to include nUnit assembly with your production code already disqualifies the first option. And this example case is just too trivial. Any production code will be too complex to be described with TestCase and would require multiple different tests. – Euphoric Oct 31 '18 at 10:36
  • 2
    And I don't see how tests don't work as "kind of documentation" in second case. If your IDE shows what lines are covered by which tests, it becomes obvious. – Euphoric Oct 31 '18 at 10:38
  • @Euphoric thank you. I also never thought about using TestCase directly in the production code, but was confused when I saw the question on SO. Your comments mention very good points, maybe consider adding this as an answer? – Thomas Flinkow Oct 31 '18 at 10:38
3

As it stands, you are not achieving anything with either approach over just having a simpler test method:

[TestFixture]
public class MathTest
{
    [Test]
    public void AddTest()
    {
        Assert.AreEqual(3, new Math().Add(1,2));
    }
}

Where [TestCase] comes into its own is in using the one method for multiple tests:

[TestFixture]
public class MathTest
{
    [TestCase(1, 2, ExpectedResult = 3)]
    [TestCase(-1, 2, ExpectedResult = 1)]
    [TestCase(-1, -2, ExpectedResult = -3)]
    public int AddTest(int a, int b)
    {
        return new Math().Add(a, b);
    }
}

But one thing is for sure: adding test data directly to your production code is generally considered a bad idea. It clutters the code and, except in trivial cases like your example, extra support code is often needed for tests, which would have to live in your production code too, further complicating things whilst thumbing its nose at the single responsibility principle.

So stick to two separate assemblies: production code and test cases, regardless of whether you use [TestCase] or not.

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.