Jack
Jack

Reputation: 117

Parameterized tests vs Test method for each case NUnit

I'm watching a course for NUnit and I came to this exercise to write a test method for below function

public static string GetOutput(int number)
    {
        if ((number % 3 == 0) && (number % 5 == 0))
            return "FizzBuzz";

        if (number % 3 == 0)
            return "Fizz";

        if (number % 5 == 0)
            return "Buzz";

        return number.ToString(); 
    }

What I did is that I have created a Parameterized test to cover all the cases like below

 [Test]
    [TestCase(15 , "FizzBuzz")]
    [TestCase(3, "Fizz")]
    [TestCase(5, "Buzz")]
    public void GetOutput_WhenCalled_ReturnString(int number , string word)
    {
        var result = FizzBuzz.GetOutput(number);
        Assert.That(result, Is.EqualTo(word));
    }

But the mentor has wrote each case in a seperate method like for example

public void GetOutput_NumberDivisiableNy3And5_ReturnFizzBuzz()
{
    var result = FizzBuzz.GetOutput(15);
    Assert.That(result, Is.EqualTo("FizzBuzz"));
}

public void GetOutput_NumberDivisiableBy3_ReturnFizz()
{
    var result = FizzBuzz.GetOutput(3);
    Assert.That(result, Is.EqualTo("FizzBuzz"));
}

My question is why he wrote it like that? does separating it like this has some advantage? or is it simply a personal preference. I'm very new to unit test and Nunit

Upvotes: 0

Views: 941

Answers (2)

Daniel Mann
Daniel Mann

Reputation: 59020

It's a personal preference.

An important guideline when testing is that the names you choose for your tests should describe the desired behavior of the method being tested for a given input. Think of the test names as being akin to executable documentation: "under circumstance X, the method should exhibit behavior Y."

Using parameterized tests means that the test name is by its very nature less descriptive, which makes it more difficult to identify at a glance exactly what's failing -- you have to look at the test parameters to determine the failing case, as the test name isn't providing you with that information.

This is apparent even in your implementation: Your test name says it "returns string" "when called". Which is technically correct, but is not descriptive. What string should it return when called with a given value?

The individual test cases, on the other hand, make the desired behavior very clear: A number divisible by 3 and 5 should return "FizzBuzz", and so on.

Also, think of it like this: What happens if you're asked to go back to this method and expand it to print Fuzz when a number is divisible by 7? And Biz when divisible by 9? And so on. Your single test method can do all of that heavy lifting, but the more requirements you have, the more burden is being put on that single test case and the harder it becomes to clearly identify which scenarios are failing and why.

Your approach isn't wrong, but if I were writing these tests, I would write one test case for each scenario: Fizz, Buzz, FizzBuzz, and not divisible by anything.

Each test case can still be parameterized, so you can test a larger number of values that satisfy each test case.

Upvotes: 1

Charlie
Charlie

Reputation: 13726

At bottom, it's a personal preference. However, when the method you are testing takes an argument, it seems very natural to use a parameterized test. OTOH, do not use a parameterized test to write a test for two or more entirely different things... in fact, don't write a test for more than one purpose at a time at all!

My guess is that your instructor is trying to start with a fundamental approach and will only introduce parameterized tests in a later lesson. But of course that's only a guess.

Upvotes: 1

Related Questions