Reputation: 43
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
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