Skip to content

Move selection before repeat#99

Open
CanYing0913 wants to merge 1 commit into
pytest-dev:mainfrom
CanYing0913:main
Open

Move selection before repeat#99
CanYing0913 wants to merge 1 commit into
pytest-dev:mainfrom
CanYing0913:main

Conversation

@CanYing0913

@CanYing0913 CanYing0913 commented Jul 16, 2026

Copy link
Copy Markdown

TL;DR

fix #15 #21 #95

Motivation

pytest-repeat currently implements repetition by adding an indirect parameter in pytest_generate_tests. As a result, pytest creates original item count × repeat count items before collection filtering and other pytest_collection_modifyitems hooks run.

For large suites and high repeat counts, this multiplies collection work even for tests that will later be deselected. In real-world cases, collection can take more than an hour while the selected tests themselves only take a few minutes.

What changed

This PR moves repeat expansion until after collection modification and deselection have completed:

  1. Collect the original test items once.
  2. Apply -k, -m, and other collection filtering/reordering plugins to the original items.
  3. Expand only the remaining items according to --count or @pytest.mark.repeat.
  4. Pass the final repeated item list to the runner and pytest-xdist.

The implementation also:

  • creates an independent item for each repetition;
  • preserves the existing [current-total] node ID suffixes, including parameterized IDs such as [param-1-10];
  • preserves function, class, module, and session repeat ordering;
  • rebuilds fixture requests and copies per-item mutable state so repetitions do not share runtime state;
  • keeps collection totals consistent with the final repeated item list.

pytest-xdist and filtering

The repeated items are created before pytest_collection_finish, so xdist workers report the final unique node IDs to the controller and each repetition can be scheduled independently.

For example:

pytest -n 4 -k important --count=10

collects the original tests, applies -k important, expands each selected test ten times, and then distributes those repeated items across workers.

Because filtering now happens before repeat expansion, -k and -m match the original test IDs and markers. Generated repeat suffixes such as [1-10] are not available as filtering targets. Final reports and xdist scheduling still use the suffixed node IDs.

Performance characteristics

Collection hooks such as pytest_itemcollected now run only for the original items, and ordinary pytest_collection_modifyitems implementations process the unexpanded list. The final runner and xdist item list still contains selected item count × repeat count entries, so execution scheduling and final item storage remain proportional to the number of repetitions.

Tests

Added coverage for:

  • repeat expansion after -k deselection;
  • collection plugins seeing only original items;
  • unique final node IDs and --collect-only totals;
  • fixture isolation between repetitions;
  • pytest-xdist execution with repeated items.

The existing parameterization, repeat marker, step number, unittest, and repeat-scope tests continue to pass.

Locally verified with:

  • pytest 6.2.5, 7.4.4, 8.4.2, and 9.0.2;
  • pytest-xdist 3.8.0;
  • flake8.

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.

Multiplying tests should happen after -k

1 participant