October 15

How to use the TestCase attribute in C# and NUnit


Learn how to use the TestCase attribute in C# when you write NUnit tests and see how it can help to remove duplication and make your tests more readable.

Do you consider yourself a motivated C#.NET developer?
Join My Productive C#

Transcript Of The Video

Hi! I'm Andrea and welcome to Productive C#. In this video I want to talk about the TestCase attribute in NUnit and how it can help to write a lot more readable tests. So here I have a solution with two projects. The first project contains the math class with a factorial static method that helps you to calculate the factorial of a number. Then I have a test project that contains the math tests class. As you can see it contains four test cases that check the factorial of zero, the factorial one, the factorial three, and the factorial five. And check the result is what we expect.

Okay, so now let's have a look at how we can use TestCase attribute to simplify this number of test. As you can see all the tests are pretty much similar. There's a lot of duplication because we call math factorial every time. We assert at equal to check the expected result is what we expect. And then basically we recognise that the main difference in the format is just the input and the output. So what we can do is the following, you can make the test metric parametric, you can accept the two input. The input and the expected result as parameters.

And then we can pass the input in the method under test and we can specify the expected result here. And then we can provide the input using the TestCase attribute. What we do in the order we pass first and in this case we pass zero and the expected result is one. So we wrote kind of a parametric test and we provide the input using an attribute. If I ran this code, I'm using the R# test runner but this works also with any runners including the NUnit test adapter in Visual Studio.

As you can see, we have the factorial zero test and zero and one is provided here as the name of the test automatically for you, so you can immediately recognise what test it is. So this means that I can remove all the three tests here and test one, three and five using additional TestCases. We can provide more than one TestCase and that's one of the advantages for using TestCase. One factorial is one, three factorial is six, and five factorial is 120.

Join My Productive C#

See how more compact this code is. Now basically I have a single test that contains all the test cases I need. Actually the name is now not represented so we should probably rename this test into something like, factorial test, for example. Alright. So now let me run it and let's have a look at how it looks. You can see the test is a single one, but under that you can see there are four different test cases. Zero one, one one, three six, and five 120. They all pass. Okay.

So this is an extremely useful attribute that I use all the time when I write tests because it really helps to improve the readability of your tests, reduce duplication a lot, and basically allows you in a very compact way to describe your tests. There's another way of doing this, that is, as you can see then there are two parameters that we pass. It's not immediately clear which parameter is which parameter, so because the expected result is something that you usually do; instead of doing the assert what you could do is return a value directly to the value that you want to assert. Right? Something like that, so we can remove that.

So we can directly return the result of the method under test and instead of passing this test result as a method, we can use here expected result as a property of the TestCase. And I can add it here in all the other tests. Okay? So what I did is now the assertion is not explicit in the test, but it reduces the number of parameters and you use a property expected result to say what you expect. So the value that you return is basically what will be asserted against the expected result that you provide here. And if you run, you can see that's pretty much the same as before, but a little bit more readable. It's actually a preference if you use this syntax or you prefer to use assert explicitely in the test. It's up to you, but it basically works the same. The difference is now that you see only zero, one, three, and five as the name of the test.

Join My Productive C#

But if you want, you can also personalise the name of the test. If you want you can say test name equals, then you can provide a particular name like, let's say, zero factorial, or you can either say zero factorial equals one. Right? I can copy that and do this. So now I can provide a custom name for each individual test case, that's up to you. I don't tend to use it, but you can do it. Now when you run it, if a test fail or pass you can immediately recognise which test you are actually looking for. And you can see here in the runners, you can definitely see the test name visualised here. So you see immediately clear what is testing.

So this is pretty much what TestCase is about. The important things to know is that TestCase values can only be compile-time values. So you if you need to provide the value, the input for your test, that's calculated at runtime you can't use TestCase. If you want to do that, you need to use TestCaseSource attribute and you can see that in another video.

But as you can see the TestCase attribute is an extremely useful attribute and can really help make your tests a lot more compact and more declarative. And that's pretty much it. Thank you very much for watching.

Join My Productive C#


.NET, Autofac, C#, Dependency Injection, Visual Studio

You may also like

The best way to stay up to date with C# 10 features

My Technical Journey from my first program to Lead Software Engineer

{"email":"Email address invalid","url":"Website address invalid","required":"Required field missing"}

Use this Bottom Section to Promote Your Offer

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim