I love parameterized tests.
Instead of many different test methods with different inputs set in the method body we have one method and pass in inputs and expected outputs for each test we want to run.
This means less test methods (so test logic is easier to change) and that we can quickly see all inputs and expected outputs for a particular method together.
In addition to this our results will be grouped together.
Below is an example from eShopOnWeb of what a parameterized test looks like and also of how the results look after a test run in Visual Studio Test Explorer.
Click on the image for a larger view in a new tab…
How can we create them in xUnit?
In the rest of this post we’ll look at the options for creating parameterized tests in xUnit …
All the code is available at the end of this post.
Method under test
Let’s say we have this very simple method below which we want to test.
It will reverse three different strings and throw an exception if an unsupported string is passed in.
Without parameterized tests
Let’s exclude testing the exception from consideration in this post as that will require a standalone test anyhow.
Here’s an example of how we can test that the three valid input strings get correctly reversed as expected using the non parameterized approach.
We can see that the tests are the same except for their input and expected output. If we had more input/output pairs we’d need to create a new test method for each one which could become difficult to maintain over time.
Parameterized tests with [InlineData]
If we use the simplest form of parametrization our test class becomes a lot cleaner …
[InlineData] is used when your test parameters are constants and you want to specify them directly in your test attribute. The arguments are provided inline, hence the name.
Ideal for a simple and small set of data.
Parameterized tests with [MemberData]
Another approach is to get the test values from a static method in the test class …
[MemberData] is used when you want to reference more complex data for your tests, or if you want to share test data across different test methods within the same class.
Parameterized Tests with [ClassData]
Finally we can also get our test data from a separate class altogether …
[ClassData] is used to load test data from a separate class which implements IEnumerable<object>.
Using this approach can be helpful when you want to share test data across multiple test classes or if you just want a convenient way of removing clutter from your test files.
What do you think?
Was this helpful?
Will you parameterize your tests to make them easier to maintain?