Calmcode - pytest tricks: parametrize twice

In pytest, you're able to stack parametrize calls.

1 2 3 4 5 6 7 8 9 10

You can test for many values in pytest in a single test by using parametrize. If you want to stack multiple variables though, it helps to recognize that you can stack these decorators on top of eachother.

Starting Point

Let's discuss an example. Suppose that we have the following test_normalise.py file. The goal will be to test a function called normalise which will accept a numpy array and output a numpy array with normalised values between 0 and 1. We're going to start by checking that the shape of the array should does not change.

import pytest
import numpy as np

def normalize(X):
    return (X - X.min())/(X.max() - X.min())

# First we generate a long set of settings
settings = []
for x in [1, 2, 30]:
    for y in [1, 2, 30]:
        settings.append((x, y))

# Next, we place them in parametrize
@pytest.mark.parametrize("x, y", settings)
def test_shape_same(x, y):
    X = np.random.normal((x, y))
    X_norm = normalize(X)
    assert X.shape == X_norm.shape

Then we can run pytest on this file via;

# The verbose setting is optional, but gives more information
pytest test_normalise.py --verbose

Parametrize

An alternative might be to stack the parametrize decorators!

import pytest
import numpy as np

def normalize(X):
    return (X - X.min())/(X.max() - X.min())

@pytest.mark.parametrize("x", [1, 2, 30], ids=lambda d: f"x={d}")
@pytest.mark.parametrize("y", [1, 2, 30], ids=lambda d: f"y={d}")
def test_shape_same(x, y):
    X = np.random.normal((x, y))
    X_norm = normalize(X)
    assert X.shape == X_norm.shape