You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Writing parametrized tests is pretty annoying. The parameter values have to be passed in as a list of anonymous tuples, so you have to rely on the order alone to figure out what's what, and the comma-delineated string for the parameter values is just asking for trouble. It also leads to a lot of indentation and useless bracket- or parentheses-only lines after it goes through a code formatter like black.
And then, if you want labels for these, you have to pass in a separate list for their ids, and make sure to keep that properly aligned with the argnames and argvalues. Overall it just seems like an unnecessary amount of bother.
What I often find myself doing is writing some variant of this helper function:
class Case:
def __init__(self, label=None, /, **kwargs):
self.label = label
self.kwargs = kwargs
def nicer_parametrize(*args):
for case in args:
if not isinstance(case, Case):
raise TypeError(f"{case!r} is not an instance of Case")
first_case = next(iter(args))
first_attrs = first_case.kwargs.keys()
argument_string = ",".join(sorted(list(first_attrs)))
case_list = []
ids_list = []
for case in args:
case_dict = case.kwargs
attrs = case_dict.keys()
if attrs != first_attrs:
raise ValueError(
f"Inconsistent argument signature: {first_case!r}, {case!r}"
)
case_tuple = tuple(value for key, value in sorted(list(case_dict.items())))
case_list.append(case_tuple)
ids_list.append(case.label)
return pytest.mark.parametrize(
argnames=argument_string, argvalues=case_list, ids=ids_list
)
That lets me write the parametrized tests in a much nicer way:
@nicer_parametrize(
Case(
"Strategy A",
flavour_prices={
"Vanilla": 1.50,
"Strawberry": 1.80,
"Chocolate": 1.80,
"Caramel": 1.65,
},
expected_revenue=1_200_000,
),
Case(
"Strategy B",
flavour_prices={
"Vanilla": 1.25,
"Strawberry": 1.55,
"Chocolate": 1.65,
"Caramel": 2.10,
},
expected_revenue=1_350_000,
),
# can also do just Case(**kwargs) if no label is needed
)
def test_ice_cream_projections(flavour_prices, expected_revenue):
...
There's one less layer of indentation, it's more explicit what each part means, the order of the named arguments don't matter, and it's impossible to get the names, values, and labels all mixed up.
It would be nice if something like this were an official part of pytest.
The text was updated successfully, but these errors were encountered:
Writing parametrized tests is pretty annoying. The parameter values have to be passed in as a list of anonymous tuples, so you have to rely on the order alone to figure out what's what, and the comma-delineated string for the parameter values is just asking for trouble. It also leads to a lot of indentation and useless bracket- or parentheses-only lines after it goes through a code formatter like black.
Example:
And then, if you want labels for these, you have to pass in a separate list for their ids, and make sure to keep that properly aligned with the argnames and argvalues. Overall it just seems like an unnecessary amount of bother.
What I often find myself doing is writing some variant of this helper function:
That lets me write the parametrized tests in a much nicer way:
There's one less layer of indentation, it's more explicit what each part means, the order of the named arguments don't matter, and it's impossible to get the names, values, and labels all mixed up.
It would be nice if something like this were an official part of pytest.
The text was updated successfully, but these errors were encountered: