pytest parameter matrices
A few months ago I explained how I efficiently test Django forms with pytest parameterization. Last week, I learned a new trick from Raphael Pierzina's post about ids for fixtures and parametrize, which is:
You you can add multiple parametrization markers to a test function which then create a test parameter matrix.
The list of test cases can thus be written much more clearly. Compare the example code from my previous post:
from django import forms import pytest class ExampleForm(forms.Form): name = forms.CharField(required=True) age = forms.IntegerField(min_value=18) @pytest.mark.parametrize( 'name, age, validity', [('Hugo', 18, True), ('Egon', 17, False), ('Balder', None, False), ('', 18, False), (None, 18, False), ]) def test_example_form(name, age, validity): form = ExampleForm(data={ 'name': name, 'age': age, }) assert form.is_valid() is validity
to the same test using multiple parameterization markers:
@pytest.mark.parametrize( 'name, valid_name', [ ('Hugo', True), ('', False), (None, False), ] ) @pytest.mark.parametrize( 'age, valid_age', [ ('18', True), ('17', False), (None, False), ] ) def test_example_form(name, age, valid_name, valid_age): form = ExampleForm(data={ 'name': name, 'age': age, }) assert form.is_valid() is (valid_name and valid_age)
This tests all 9 possible combinations of the three test cases each for name
and age
. Maybe that's overkill, but on the other hand I can be sure that I touch all the relevant combinations.
Take note of the last line that checks that the form only validates when both input parameters are valid.
The main advantage I see is legibility. For each form field, I only have to understand the list of test parameters for exactly that field, and not any additional combinations with other fields.
I'm loving it!