We can't find the internet
Attempting to reconnect
Something went wrong!
Attempting to reconnect
← Testing with pytest and Hypothesis step 9 of 19
Expand parametrize Tables into Test Cases
@pytest.mark.parametrize turns its table into test cases. It pairs each
row's values with the names and calls the test once per row. Stacked
decorators give every combination of two tables.
The grader cannot run pytest, so here you write a simplified version of that expansion yourself. Each test case is a dictionary from parameter name to value.
expand_parametrize("a, b", [(1, 2), (3, 4)])
# [{"a": 1, "b": 2}, {"a": 3, "b": 4}]
stack_parametrize([{"x": 0}, {"x": 1}], [{"y": 2}, {"y": 3}])
# [{"x": 0, "y": 2}, {"x": 1, "y": 2}, {"x": 0, "y": 3}, {"x": 1, "y": 3}]
Expand one table
def expand_parametrize(
argnames: str, argvalues: Sequence[object]
) -> list[dict[str, object]]
Split argnames on commas and strip the spaces around each name. Then
apply these rules in order:
- If any name is empty, raise
ParametrizeErrorwith the messagef"empty argname in {argnames!r}". Use the original string, with its spaces. Check this first, even whenargvaluesis empty. - With one name, each element of
argvaluesis the whole value. Soexpand_parametrize("xs", [[1, 2], [3]])returns[{"xs": [1, 2]}, {"xs": [3]}]. Do not unpack the inner lists. - With several names, each row must be a list or a tuple with one value per name. Pair the values with the names in order.
Keep the rows in order, with a new dictionary for each row. Put the value
objects themselves in it, without copying them. With valid names and an
empty table, return [].
A name may repeat, although real pytest rejects that. Count every name
when you check a row's length, and let the last value win, so names
"x,x" and row [1, 2] give {"x": 2}. Do not check whether a name is a
valid Python identifier.
Report a bad row
With several names, check the rows from first to last, and stop at the first bad one. Check its type before its length. With two names, the messages look like this:
argvalues[1] is not a list or tuple but there are 2 argnames
argvalues[1] has 1 values but there are 2 argnames
Put in the row's index, counting from 0, and the real counts. Keep the word
values even when the count is 1. A string such as "xy" is a sequence,
but it is not a valid row for two names. With one name, it is a fine whole
value.
Combine two tables
def stack_parametrize(
first: Sequence[Mapping[str, object]],
second: Sequence[Mapping[str, object]],
) -> list[dict[str, object]]
Return a list with one new dictionary for every pair of rows. Loop over second on the
outside and first on the inside, as in the example above. That is
pytest's order when the upper decorator supplies x and the lower one
supplies y.
Copy the first row's entries, then the second row's, so the second
value wins when both rows have a key. Keep nested values as they are, and
do not change either input. If either table is empty, return [].
What the driver reports
Keep solve as it is. It expands the main table into cases. If stack
is None, stacked is an empty list. Otherwise solve expands the
stack table too and puts the combined rows in stacked. On success,
error is empty.
If either expansion raises ParametrizeError, solve returns empty
cases and stacked lists with the message in error, even when only the
stack table is bad. It expands the stack table even when the main table
is empty.
Your code, saved here
Sign in to access your accepted solutions and saved draft history. You can keep reading the lesson without an account.
Sign in to your accountStuck?
Python reference solution
Sign in to track your attempts toward unlocking the reference solution.