Skip to content

Fix CLI options ignored when --looponfail runs with -n (#767)#1340

Open
golikovichev wants to merge 2 commits into
pytest-dev:masterfrom
golikovichev:fix/767-looponfail-tbstyle
Open

Fix CLI options ignored when --looponfail runs with -n (#767)#1340
golikovichev wants to merge 2 commits into
pytest-dev:masterfrom
golikovichev:fix/767-looponfail-tbstyle

Conversation

@golikovichev

Copy link
Copy Markdown

Fixes #767.

Problem

pytest --tb=short -n2 --looponfail ignores --tb=short and prints a long traceback. The option is only dropped when --looponfail and -n are combined; each on its own respects --tb=short.

Root cause

--looponfail rebuilds the worker session config via Config.fromdictargs(option_dict, args), where args is the positional test paths only. fromdictargs sets config.invocation_params.args to exactly those positional arguments, so the original command-line flags (e.g. --tb=short) are not present there, even though config.option carries them.

That is fine for looponfail's own in-process run, which reads config.option directly. But when looponfail runs a nested distributed (-n) session, WorkerController.setup builds the nested worker argv from config.invocation_params.args (workermanage.py). Since the flags are missing there, the nested workers fall back to their defaults, including the long traceback style.

Fix

Pass the original invocation arguments to the looponfail worker and restore a faithful config.invocation_params.args after fromdictargs. This propagates all command-line flags (not just --tb) to nested workers. dataclasses.replace is used because InvocationParams is a frozen dataclass; plugins and dir are preserved.

Tests

Added a regression test in testing/test_looponfail.py that runs the failing tests through RemoteControl.loop_once() with -n2 --tb=short and asserts the short-style traceback markers appear (and the long-style source expansion does not).

Verified locally:

  • New test fails without the fix, passes with it.
  • Full testing/test_looponfail.py passes (no regressions).
  • ruff check, ruff format --check, and mypy are clean.
  • The original reproduction command from the issue now prints a short traceback.

When --looponfail runs the failing tests through distributed (-n) workers,
the worker session config was rebuilt only from the parsed options and the
positional arguments, so config.invocation_params.args lost the original
command-line flags such as --tb=short. xdist reads invocation_params.args
to replicate options on its workers, so the nested workers fell back to
their defaults (for example, the long traceback style).

Restore the full invocation arguments in the looponfail worker config so
those options propagate to the nested workers.

Closes pytest-dev#767
dataclasses.replace() raises TypeError on pytest 7.x, where
InvocationParams is a frozen attrs class rather than a dataclass. Build
the replacement through the type's own constructor instead, which works
for both the attrs (7.x) and dataclass (newer pytest) variants.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

--tb=short option ignored when combined with -n2 and --looponfail

1 participant