Pytest Parametrization: One test to rule them all

We learned testing the hard way 

Software testing is ignored by most university courses, but absolutely essential when you get in the field and need to deliver a software product. Without fail, the first time you arrive at a workplace as a developer, you write your first piece of code, you proudly submit it for review, and that is when your colleague comments: where are the tests?. Shortly after comes panic, followed by hyper-speed learning of testing libraries. Then, you write some post-coding tests full of regrets while scrambling to get that >99% coverage to your manager.  

Now, after you’ve got the gist of testing, you have learned to develop the tests and code continuously. If you are a real testing ninja perhaps you even write the tests BEFORE the code (what?! ?). Even so, we can improve our testing in countless ways. 

An alternative to repetitive test writing 

How many times have you been writing countless single unit tests covering every possible edge case with a different manually written test? 

 

Today, let’s talk about writing a single test to neatly cover many test cases. As coders, we strive to solve every problem only once and reuse our code. We want to make robust code that can serve several purposes. Clearly, the single-purpose code – like the plastic wrapper of the software world – is missing the mark when it comes to reusability. 

Writing a parametrized test 

When we are testing Python code, we can utilize Pytest’s parametrize() functionality to create a single test that covers many possible cases. 

Take for example this test, where a two-line test has been configured to test several cases. In this case, we are testing a function that takes the parameters “ingredients” and “dressing”, and it lets us know whether it is a tasty salad recipe. The “expected” output is True or False depending on whether we expect the salad to be tasty. Finally, the optional “id” parameter is a human-friendly name for the test case. 

Of course, this software – as yours truly – is partial to tomatoes ? but does not care for celery ?. 

Test expected errors in parametrized tests 

Taking it to the next level, we can also test whether a crazy salad idea incurs the expected errors. Here is someone who has thought to add a number 3 to the salad. Now, this will certainly cause an error as we did not expect any numbers showing up in the salad, and we can test whether the expected error occurs.  

We use pytest.raises() to specify an expected error, and to test error-free cases, we have created a special function using contextmanager from contextlib for when we are expecting no error. 

 

There we have it. Pytest provides several tools for us to streamline test writing, and parametrization is a great tool to have up your sleeve for those days writing infinite unit tests. 

Certainly, we will be much more likely to cover those corner cases of our software when we have to make less effort to add additional test cases. 

 

Anneli Pedersen

Full Stack Developer at EKKIDEN

Leave a Reply

Your email address will not be published. Required fields are marked *