Using TestCase arrtibute of NUnit

December 7th, 2009 by ganton | Print

Sometimes ago NUnit extend their framework with a possibility to specify parameters via an attribute and then these parameters are reused by NUnit run-time and the test method is executed several times with different parameters. An example: let’s assume that we have a method that concatenates person first name and person last name.

   1: //…..

   2: public void ConcatenateNames(string firstName, string lastName)

   3: {

   4:     if(string.IsNullOrEmpty(firstName))

   5:         throw new ArgumentNullException("message");

   6:     if(string.IsNullOrEmpty(lastName))

   7:         throw new ArgumentNullException("message");

   8:  

   9:     // concatenate

  10: }

We need to test this method for invalid and valid arguments. If arguments are invalid we should expect an exception, otherwise we should check if it concatenates person’s names correctly. We can easily do this using TestCase attribute and not repeating the same code in several test methods.

   1: [Test]

   2: [TestCase(null, null, ExpectedException = typeof(ArgumentNullException))]

   3: [TestCase(null, "Gochev", ExpectedException = typeof(ArgumentNullException))]

   4: [TestCase("Anton", null, ExpectedException = typeof(ArgumentNullException))]

   5: [TestCase("Anton", "Gochev", ExpectedException = typeof(ArgumentNullException))]

   6: public void ConcatenateNamesTest(string firstName, string lastName)

   7: {

   8:     myClassInstance.ConcatenateNames(firstName, lastName);

   9:  

  10:     // Assert if everything is correct.

  11: }

Nice, isn’t it? TestCase attribute simplifies testing for invalid and valid parameters  and reduces the code that we produce as test methods.

But what if ConcatenateNames method accepts an object Person and should do the same work. In this case we have a small problem. We cannot pass to an attribute something like new Person { FirstName = “”, LastName = “”}. The information of the attribute is stored in class meta-data and consequently attribute’s information is pre-defined but not evaluated during run-time processing. Fortunately, we still can use TestCase attribute but not providing Person object but a bool variable that will allow us to know whether to initialize the object or not.

   1: [Test]

   2: [TestCase(false, ExpectedException = typeof(ArgumentNullException))]

   2: [TestCase(true)]

   3: public void ConcatenateNamesTest(bool initializePerson)

   4: {

   5:     Person person = null;

   6:     if(initializePerson)

   7:         person = new Person { FirstName = "Anton", LastName = "Gochev" };

   8:  

   9:     myClassInstance.ConcatenateNames(person);

  10:  

  11:     // assert everything is correct

  12: }

Well, this example is not a real one but I hope you got the idea. I know that many developers will say that it is not really good practice because you have more logic then just to check methods correctness inside the test but for me it is OK. It saves me a lot of additional test method writing (in more complex cases) and I’m fine with this approach.

Leave a Reply