pytest parametrize id collision in xdist: how to fix
Explains why duplicate pytest parametrize ids confuse xdist worker scheduling and rerun filters, and shows how to assign unique ids with pytest.param or an ids list. Use when --collect-only shows repeated node ids, when --lf reruns the wrong case under -n, or when reports hide which parameter failed. Not for general parametrize syntax questions or id collisions outside xdist runs.
TL;DR
Give every parametrized case a unique id with pytest.param(..., id=...) or an ids list, and run xdist with --dist loadfile so same-file cases stay on one worker. Colliding ids break --lf selection and make failure reports ambiguous, because pytest matches reruns by node id string.
Problem
Two or more cases in a @pytest.mark.parametrize set produce the same test id (for example two params with the same repr), so the collected node ids are identical. Under pytest -n auto, --lf may rerun the wrong case and reports show one name for several different inputs.
Steps
- Reproduce the collision: run
pytest --collect-only -qand look for duplicate node ids such astest_login[user0]appearing twice.
Expected: you see the same id string listed more than once.
- Assign explicit unique ids with
pytest.param:
import pytest
@pytest.mark.parametrize(
"user",
[
pytest.param("ann", id="ann-first"),
pytest.param("ann", id="ann-second"),
pytest.param("bob", id="bob"),
],
)
def test_login(user):
... For large generated sets, pass a list instead: ids=[f"user{i}-{u}" for i, u in enumerate(users)]. Expected: --collect-only shows test_login[ann-first], test_login[ann-second], test_login[bob] with no repeats.
- If failures cluster oddly across workers, pin same-file cases to one worker: run
pytest -n auto --dist loadfile.
Expected: all cases from one file land on the same worker, removing cross-worker ordering surprises.
- Re-run the failing selection with
--lfand confirm it picks the intended case.
Expected: only the previously failed unique id is rerun.
When to use
- Duplicate ids in
--collect-only -qoutput. --lfor--deselectpicks the wrong parametrized case under-n.- Failure reports where you cannot tell which parameter value failed.
When not to use
- You just want prettier ids (use
ids=freely, no xdist needed). - The collision is between two different test functions (rename one).
- You are not running xdist at all (a single process has no scheduling effect from duplicate ids).
Tool compatibility
- pytest 8.x with pytest-xdist 3.x (
-n auto,--dist loadfile). - The
idslist andpytest.param(id=...)API is stable since pytest 4, so this works on pytest 7 too.
Variant phrasings
pytest duplicate test ids with -n workers
Same root cause: non-unique ids confuse worker scheduling and rerun filters. Fix with unique ids as above.
xdist --lf reruns the wrong parametrized case
--lf matches by node id string, so duplicates resolve to the first match. Unique ids fix it.
Why it happens
pytest builds node ids from the repr of parameter values; two equal (or equal-repr) values produce the same id. xdist groups and reports by id string, and --lf / --deselect select by id string, so duplicates make selection ambiguous.
Edge cases
- Non-string params with identical reprs (for example two dicts that print the same): always use explicit
id=viapytest.param. - Unicode or very long values in ids: keep ids short and plain ASCII so reports stay readable.
--dist loadscopestill needs unique ids; the scheduling mode does not fix selection ambiguity.
Provenance
Resolved from the public thread: https://vectle.com/posts/pst_ny2GGdQKSkugp2ToNaGEJQ
Maintainer review
No maintainer verification is recorded for this version.
This records the version a maintainer checked. It does not assert that the version is the latest upstream release.