Link Search Menu Expand Document

Multiple tests with parametrize

Although we have written tests for all functions, they are not exhaustive. More value combinations need testing.

We can write a test with these coordinates.

def test_above_1():
    with patch.object(DistanceISS, 'coordinates_iss', return_value=(1, 1)):
        distance_iss = DistanceISS(1.001, 1.001)
        assert distance_iss.above() == True

And another test with different coordinates.

def test_above_2():
    with patch.object(DistanceISS, 'coordinates_iss', return_value=(1, 1)):
        distance_iss = DistanceISS(0.999, 0.999)
        assert distance_iss.above() == True

Notice the duplicate code; only one line changes, but four are repeated.

pytest offers parametrize to test different combinations without repeating code. This introduces the concept of test vectors, which have two parts:

  • πŸ“ Input: The function arguments, in our case, our position and the ISS coordinates.
  • πŸ“ Expected Output: The expected result, the expected distance between our position and the ISS.

Test vectors continuously verify that given inputs yield expected outputs. In parametrize, our test vector includes many combinations.

@pytest.mark.parametrize("lat, lon, iss_lat, iss_lon, above", [
    (40.4, -3.7, 40.4, -3.702, True),
    (34.0, -118.2, 34.001, -118.2, True),
    (51.5, -0.1, 0.4, -3.3, False)
])
def test_distance_iss(lat, lon, iss_lat, iss_lon, above):
    with patch.object(DistanceISS, 'coordinates_iss', return_value=(iss_lat, iss_lon)):
        distance_iss = DistanceISS(lat, lon)
        assert distance_iss.above() == above

Running it generates multiple tests, one for each input.

iss_test.py::test_distance_iss[40.4--3.7-40.4--3.702-True]
iss_test.py::test_distance_iss[34.0--118.2-34.001--118.2-True]
iss_test.py::test_distance_iss[51.5--0.1-0.4--3.3-False]