Sometimes you might get yourself in a situation where you need to test the same method or function with a variety of different parameters. This is very common and when it happens we have two usual ways to deal with it:
- write a new spec for each combination of parameters
- write one spec and use data provider approach
For the sake of this article, I'm gonna use a very dummy example. Imagine a method that receives the sides of a triangle as parameters and returns its type :
We can easily write 3 specs and cover it:
Well, nothing is wrong with it, and you have the advantage that, if one of these specs fail, you can easily identify what business rule has an issue and address it quickly, but if you look closer you'll notice that we are basically duplicating code here and only changing the parameters and expected results based on them.
This is when the data provider pattern can be useful. So, instead of having code duplication, you create an array of cases, iterate over it and do the assertions:
In the case of this dummy example, which is very simple and it's totally fine to create more specs for each business rules, but sometimes you might end up trying to cover some tests that would require so many lines of code duplications that you may consider the data provider pattern, not because you want to avoid code duplications, but because in some situations it will help you to also maintain the code.
If you're using JEST, there's also one extra method provided by the framework that can be used instead of the foreach: The each method.
So we could refactor a bit the previous code and turn it into:
the outcome is:
Pretty neat, right?
This makes life way easier for example, if you need to introduce more test cases, besides reducing unit tests boilerplate.
In case you were not familiar with this approach yet, I’d suggest you to be a bit careful. Sometimes it might be tempting to go for it, as you’re reducing a lot of code, but it also comes with a price:
- you might be introducing more abstractions;
- Debugging might get complex;
So, my advice is to always be careful and think about what you want to achieve. How complex is the test you’re doing? Would it make sense to have specs per business rules? With one generic spec, if you stay around 1 year without touching this code and then it starts failing, would it be straight forward to identify the issue based on the test? Would it had been easier if you would have duplicated the specs and have them isolated?
I normally try to ask myself these questions and then decide based on it. I also like to write specs based on the business rules as it makes life easier for me to remember it.
Ah, and as a general advice from Robert C. Martin (author of Clean Code):
Keep your tests clean. Treat them as first-class citizens of the system.
Now, what is your opinion about the data provider pattern? Do you find it useful? Please let me know in the comments!