๐Ÿ Python tips 3: Writing tests faster with pytest.parametrize ยท daolf

๐Ÿ Python tips 3: Writing tests faster with pytest.parametrize

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.

If you like those short blog post about Python you can find my 2 previous one here:

Happy coding

If you liked this article, you can follow me on Twitter, I tweet about bootstrapping, indie-hacking, startups and code ๐Ÿ˜Š
comments powered by Disqus