luggzy
luggzy

Reputation: 43

pytest: paramaterized tests vs explicit tests

I'm new to pytest, and I'm looking to clear up a bit of confusion I have regarding paramaterized tests.

Is it better (i.e. clearer, more DRY, more maintainable) to use a single parameterized test function, or multiple explicit tests that only differ in their 'input'?

Let me give an example to hopefully better explain my point:

Say we have written a simple function, merge_sort, and we want to test it using various inputs, for example including negative numbers, repeated numbers, floats etc.

Writing multiple explicit tests:

def test_merge_sort():
    unsorted = [2, 1, 3]
    expected = [1, 2, 3]

    assert merge_sort(unsorted) == expected

def test_merge_sort_negative():
    unsorted = [-2, -1, -3]
    expected = [-3, -2, -1]

    assert merge_sort(unsorted) == expected

def test_merge_sort_including_zero():
    unsorted = [2, 0, 1]
    expected = [0, 1, 2]

    assert merge_sort(unsorted) == expected

def test_merge_sort_repeated_number():
    unsorted = [0, 1, 0]
    expected = [0, 0, 1]

    assert merge_sort(unsorted) == expected

def test_merge_sort_float():
    unsorted = [0.1, 0.3, 0.2]
    expected = [0.1, 0.2, 0.3]

    assert merge_sort(unsorted) == expected

OR, writing a single, paramaterized test:

@pytest.mark.parametrize("unsorted,expected", [
    ([2,1,3], [1,2,3]),
    ([-2,-1,-3], [-3,-2,-1]),
    ([2,0,1], [0,1,2]),
    ([0,1,0], [0,0,1]),
    ([0.1,0.3,0.2], [0.1,0.2,0.3]),
])
def test_merge_sort(unsorted, expected):
    assert merge_sort(unsorted) == expected

My initial thought is that multiple explicit tests is clearer and more maintainable, as if there are failures, you would get a descriptive function name indicating the specific case under test. However, the parameterized test is more DRY, and it would potentially be easier to extract the test data as a fixture for other tests (i.e. using the same data to test a quick_sort function).

Perhaps there is something I have missed in the pytest docs which answers this?

Thanks in advance for any help!

Upvotes: 3

Views: 279

Answers (1)

user395760
user395760

Reputation:

The failure message will include all the parametrized values, so you can add a description text to the parameters:

@pytest.mark.parametrize("description,unsorted,expected", [
    ("positive", [2,1,3], [1,2,3]),
    ("negative", [-2,-1,-3], [-3,-2,-1]),
    ("including zero", [2,0,1], [0,1,2]),
    ("duplicate values", [0,1,0], [0,0,1]),
    ("floats", [0.1,0.3,0.2], [0.1,0.2,0.3]),
])
def test_merge_sort(description, unsorted, expected):
    assert merge_sort(unsorted) == expected

Upvotes: 4

Related Questions