As software engineers, we can all agree that tests are a very important part of every piece of software that we create. Our approach to writing tests is a completely different topic. Some of us love TDD, while others usually write tests after a feature has been implemented.
In this article, I’ll only be focusing on parameterized tests because I believe that this way of writing tests can sometimes be simpler and more readable.
What Will You Get From This Article?
- A brief look at what declarative programming is and is not.
- How to write parameterized tests in JavaScript.
- Determining the right time to use these kinds of tests.
- Pros and cons of writing parameterized tests.
Declarative — What’s the Big Deal?
I convinced myself to use the declarative paradigm when I started writing in React, but what’s the big deal about it?
The declarative paradigm is usually compared to the imperative paradigm. In imperative programming, we focus on how we want to achieve our goal. On the other hand, declarative programming is more about what we want to achieve. Tyler McGinnis offered a great example in his article on this topic:
“I’m right next to Wal-Mart. How do I get to your house from here?”
Imperative response: Go out of the north exit of the parking lot and take a left. Get on I-15 North until you get to the 12th street exit. Take a right off the exit like you’re going to Ikea. Go straight and take a right at the first light. Continue through the next light then take your next left. My house is #298.
A declarative response: My address is 298 West Immutable Alley, Eden, Utah 84310
How to Write Parameterized Tests
I’ve prepared the GitHub repository with some boilerplate code written in JavaScript. First, let’s see how the test will look when all parameters are specified inside the tests:
These tests are written in an imperative way. In each test, I’ve followed the same steps:
- Create a book.
- Check if the book is valid.
- Assign the result to a variable.
- Check if the result is the same as we expected to be.
Now let’s see how we can separate the parameters in each test from the test logic:
As you can see, we left only the test logic that checks if a created book is valid, but all the parameters are in a different JSON file:
Because we moved the parameters to a different file, we can easily add new test cases.
There are a lot of libraries that allow us to write parameterized tests (e.g jest-each). Using this particular library is quite easy. You can specify test cases by an array of arrays, where each array is a new test case and each element in the array is another argument of the test function:
Or by using a template string instead of an array of arrays:
This solution seems to be perfect for easier cases, but for more complex tests where we need to inject some services or repositories, it is better to use a JSON file with test cases specified out there because of separation and increased readability.
When to Use Parameterized Tests
Use
Of course, it depends. You didn’t expect a different answer, did you? The best scenario for these kinds of tests is a situation where we have a lot of test cases for one test — like in the example above, where we tested some kind of book’s validation for different data. Another example can be a repository where we want to check each of CRUD methods for a different set of data to be sure that we touch every case.
Don’t use
On the other hand, you shouldn’t use parameterized tests in situations where you test one set of data. Separating the data from the test would be overkill.
Pros/Cons of Parameterized Tests
Pros
- Create a test once and then only add new test cases.
- The test logic is separated from the test cases.
- A JSON file with the test cases can be easily shared with other team members without concern that anybody will break your tests.
- With JSON schema validation, tests can be shared with team members who are less technically proficient (e.g. manual testers).
- They follow the DRY principle.
Cons
- Separating the test logic from the test parameters requires additional work.
- Overkill for tests with only a few cases to check.
- An additional file with test cases (not required).
Conclusion
The purpose of this article was to show that in some cases, writing these types of tests can be a simple and clean alternative. That was just a simple example of parameterized tests and my way of doing it. If you want to see more, I recommend checking out my repository for the full application.
I hope this short article delivered what I promised at the beginning.
Thanks for reading!
Twitter: k_wdowik