Skip to content

pytest.ini's prescribed local invocation is red: autobot-slm-backend alone fails an order-dependent test CI never sees #16075

Open

Description

@mrveiss

What

pytest autobot-slm-backend — the local invocation pytest.ini itself prescribes — fails on current Dev_new_gui. CI passes the same tree, because CI's command is not that command.

autobot-slm-backend/services/hf_token_validator_test.py::TestProbeHfTokenValid::test_200_is_valid
E   AttributeError: module 'services' has no attribute 'hf_token_validator'.
    Did you mean: 'hf_token_validator_test'?
1 failed, 499 passed

The invocations differ, and the difference is what hides it

pytest.ini:64-73 tells a developer to run two invocations, the second being autobot-slm-backend alone. .github/workflows/ci.yml:338-347 runs:

python -m pytest autobot-slm-backend \
  -n auto --dist loadscope \
  -p repo_tests.stable_shard \
  --shard-splits 12 --shard-group N --shard-durations .test_durations_slm \
  -m "not integration and not slow and not distributed and not performance"

--dist loadscope keeps a module's tests on one worker and distributes modules across twelve. Sequential collection puts them in a single interpreter in collection order. The failing test is order-dependent, so the two shapes disagree.

Verified against CI rather than assumed: shard 8/12 on 2845e68abb is success with zero FAILED lines, and its log names this exact node — hf_token_validator_test.py::TestProbeHfTokenValid::test_200_is_valid — being handled. CI runs it and it passes there.

Why it fails sequentially

conftest.py real-loads hf_token_validator and binds it onto the services stub, and its own comment says why:

hf_token_validator #14307 — co-located test, same shard-order dependency.

and for its neighbour:

Its co-located test passed only when tests/services/conftest.py happened to be collected first in the same shard, which pytest-split decides.

The binding does not survive another module replacing sys.modules['services'] wholesale. That is not hypothetical — the successful CI shard emits it as a warning:

sys.modules['services'] was replaced by autobot-slm-backend/services/a2a_card_fetcher_test.py
  and is STILL INSTALLED while pytest handles ...

Eight distinct owners leak inside that one shard. Under loadscope the collision happens to miss; sequentially it lands.

Why this matters beyond one test

The documented local command is red while CI is green, so a developer following pytest.ini sees a failure that no reviewer can reproduce and no CI run reflects. The natural readings are "my environment is broken" or "base is broken", and both are wrong. That is expensive in the same way the two-range confusion on #16069 was: the output is accurate and answers a different question from the one being asked.

It also means the pre-push hook's fix in #16074 restores CI's path partitioning but not CI's distribution, so a local run can still diverge. #16074 is still correct and still necessary; this is a separate axis.

Acceptance criteria

  • pytest autobot-slm-backend passes on a clean checkout of base, or pytest.ini stops prescribing a command that does not
  • The specific ordering dependency is removed rather than reordered around — the stub that replaces sys.modules['services'] installs and removes in the same try/finally, scoped to the nodes that need it
  • A test fails if hf_token_validator resolves to a stub, verified by a mutation rather than by reading (the current failure mode is an AttributeError, but a MagicMock resolution would pass silently)
  • The eight leaking owners inside the slm-alone shard are enumerated, and each is either fixed or recorded with a reason

Provenance

Observed by a peer session running the two-invocation shape by hand, and explicitly offered as an observation rather than a finding pending a check against CI's invocation. That check is above: it does not reproduce under CI's command, and it does reproduce the documented one. Related: #16069 (conftest stubs escaping their directory), #14307 (the real-load list this depends on), #13084 (the identical-package-name collision).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions