Write your Python tests faster with parametrize
I think there is no need to explain here how important testing your code is. If somehow, you have doubt about it, I can only recommend you to read those great resources:
But more often than not, when working on your side projects, we tend to overlook this thing.
I am in no way advocating that every code you write in every situation should be tested, it is perfectly fine to hack something and never test it.
This post was only written to show you how to quickly write Python tests using pytest
and one particular feature, hoping it will reduce the amount of non-tested code you write
Writing some tests
We are going to write some tests for our method that takes an array, removes its odd member, and sort it.
This will be the method:
def remove_odd_and_sort(array):
even_array = [elem for elem in array if not elem % 2]
sorted_array = sorted(even_array)
return sorted_array
That's it. Let's now write some basic tests:
import pytest
def test_empty_array():
assert remove_odd_and_sort([]) == []
def test_one_size_array():
assert remove_odd_and_sort([1]) == []
assert remove_odd_and_sort([2]) == [2]
def test_only_odd_in_array():
assert remove_odd_and_sort([1, 3, 5]) == []
def test_only_even_in_array():
assert remove_odd_and_sort([2, 4, 6]) == [2, 4, 6]
def test_even_and_odd_in_array():
assert remove_odd_and_sort([2, 1, 6]) == [2, 6]
assert remove_odd_and_sort([2, 1, 6, 3, 1, 2, 8]) == [2, 2, 6, 8]
To run those tests simple pytest <your_file>
and you should see something like this:
As you can see it was rather simple, but writing 20 lines of codes for such a simple method can sometimes be seen as a too expensive price.
Writing them faster
Pytest is really an awesome test framework, one of its features I use the most to quickly write tests is the parametrize
decorator.
The way it works is rather simple, you give the decorator the name of your arguments and an array of tuple representing multiple argument values.
Your test will then be run one time per tuple in the list.
With that in mind, all the tests written above can be shortened into this snippet:
@pytest.mark.parametrize("test_input,expected", [
([], []),
([1], []),
([2], [2]),
([1, 3, 5], []),
([2, 4, 6], [2, 4, 6]),
([2, 1, 6], [2, 6]),
([2, 1, 6, 3, 1, 2, 8], [2, 2, 6, 8]),
])
def test_eval(test_input, expected):
assert remove_odd_and_sort(test_input) == expected
And this will be the output:
See? And in only 10 lines. parametrize
is very flexible, it also allows you to defined case the will break your code and many other things as detailed here
Of course, this was only a short introduction to this framework showing you only a small subset of what you can do with it.
You can follow me on Twitter, I tweet about bootstrapping, indie-hacking, startups and code ๐
Happy coding
If you like those short blog post about Python you can find my 2 previous one here: