Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TDD nUnit multiple asserts for one method

Tags:

c#

nunit

Using TDD first time in my life today. I am using nUnit.

I have one method, where I can insert multiple different inputs and check if result works.

I read that multiple asserts in one test is not a problem, and I really don't want to write new test for each input.

Example with multiple asserts:

    [TestFixture]
public class TestClass
{

    public Program test;

    [SetUp]
    public void Init()
    {
        test = new Program();

    }
    [Test]
    public void Parse_SimpleValues_Calculated()
    {
        Assert.AreEqual(25, test.ParseCalculationString("5*5"));
        Assert.AreEqual(125, test.ParseCalculationString("5*5*5"));
        Assert.AreEqual(10, test.ParseCalculationString("5+5"));
        Assert.AreEqual(15, test.ParseCalculationString("5+5+5"));
        Assert.AreEqual(50, test.ParseCalculationString("5*5+5*5"));
        Assert.AreEqual(3, test.ParseCalculationString("5-1*2"));
        Assert.AreEqual(7, test.ParseCalculationString("7+1-1"));
    }
}

But when something fails it is very hard to read which assert failed, I mean if you have them a lot, you have to go through all and find the right assert.

Is there any elegant way to show what input did we set if assert fails, instead of result and expected result?

Thank you.

like image 451
sensei Avatar asked Aug 18 '13 18:08

sensei


1 Answers

I mean if you have them a lot, so you have to go through all.

No you don't - you just look at the stack trace. If you're running the tests within an IDE, I find that that's easily good enough to work out which line failed.

That said, there is a (significantly) better way - parameterized tests with TestCaseAttribute. So for example:

[Test]
[TestCase("5*5", 25)]
[TestCase("5*5*5", 125)]
[TestCase("5+5", 10)]
// etc
public void Parse_SimpleValues_Calculated(string input, int expectedOutput)
{
    Assert.AreEqual(expectedOutput, test.ParseCalculationString(input));
}

Now your unit test runner will show you each test case separately, and you'll be able to see which one fails. Additionally, it will run all of the tests, even if an early one fails - so you don't end up fixing one only to find that the next one failed unexpectedly.

There's also TestCaseSourceAttribute for cases where you want to specify a collection of inputs separately - e.g. to use across multiple tests.

like image 171
Jon Skeet Avatar answered Oct 15 '22 09:10

Jon Skeet