Skip to content

fix(tests): an optional-dependency gate skips its cells, not the whole module - #3757

Merged
cagataycali merged 1 commit into
strands-labs:mainfrom
cagataycali:fix/optional-dep-gate-mutes-module
Sep 16, 2026
Merged

cagataycali merged 1 commit into
strands-labs:mainfrom
cagataycali:fix/optional-dep-gate-mutes-module

Conversation

@cagataycali

Copy link
Copy Markdown
Member

gate scope, measured

What pytest.importorskip raises rather than returning None, and a decorator is evaluated at import, so @pytest.mark.skipif(pytest.importorskip("x") is None, ...) skipped the whole file rather than the cell it named. Two gates were written that way. Both now read presence as a spec (importlib.util.find_spec), the convention the rest of the suite keeps, and a whole-tree guard refuses the shape.

Why Without the extra, each file collected nothing: 17 cells needing no zmq and 33 needing no mujoco, dropped by gates protecting the 18 that do. A merge check installs every extra, so all 68 ran there and read green.

Tests The guard fails on the pre-fix tree naming both offenders and passes after (11 cells); 5/5 mutants caught; a subprocess pin measures both spellings (none collected vs 2 passed, 1 skipped). The two files still run 68 cells; ruff, format and mypy clean. #3343 edits the same sim module but neither the gate nor its imports.

… the whole module

pytest.importorskip raises Skipped rather than returning None, and a decorator
is evaluated while the module is imported, so a gate written as
@pytest.mark.skipif(pytest.importorskip("x") is None, ...) skips the whole file
instead of the test or class it sits on. Two gates were written that way. On an
interpreter without the extra, each file collected nothing at all: the policies
kwargs module lost 17 cells that need no zmq, and the sim describe module lost
33 that need no mujoco - 50 cells dropped by gates protecting the 18 that do.
A merge check installs every extra, so it collected all 68 and read green.

Both now read presence as a spec, the convention the rest of the suite keeps,
and a new whole-tree guard refuses the shape so it cannot return.
@cagataycali
cagataycali enabled auto-merge (squash) September 16, 2026 09:03

@yinsong1986 yinsong1986 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Summary

Fixes two optional-dependency gates that were written as @pytest.mark.skipif(pytest.importorskip("x") ...) — a shape that raises Skipped at module import time, muting every test in the file instead of just the gated cell (50 unrelated cells dropped on interpreters without the zmq/mujoco extras, invisible in CI because the merge check installs all extras). Both gates now read presence via importlib.util.find_spec, matching the suite's existing convention, and a new tree-wide AST guard (tests/test_an_optional_dependency_gate_does_not_mute_its_module.py) refuses the broken shape going forward.

What's good

  • The new guard distinguishes scope-disagreeing gates (decorator-position importorskip) from legitimate uses (module-scope deliberate mutes, test-body calls, spec-based gates), with parametrized positive and negative cases pinning the predicate.
  • Behavioural pin runs a synthetic module in a subprocess and asserts the actual collected/skipped counts for both spellings — tests the outcome, not the implementation (AGENTS.md convention 9).
  • The test_both_test_trees_are_scanned self-check guards against the sweep silently narrowing; the > 1000 threshold holds against the current tree (1809 test modules under tests/ + tests_integ/).
  • Test-only change with no public API, wire-format, or security surface; the subprocess invocation uses literal argv only.

Verification suggestions

On an interpreter without the extras (pip uninstall zmq mujoco in a scratch venv), confirm the two fixed files now collect their independent cells:

pytest tests/policies/test_a_misspelled_provider_kwarg_is_refused_naming_the_one_meant.py -q
pytest tests/simulation/test_sim_engine_describe_discovery.py -q

Expect 17 passed / 1 skipped and 33 passed / 17 skipped respectively, per the table in the guard module's docstring.

auto-merge was automatically disabled September 16, 2026 11:50

Pull request was closed

@cagataycali cagataycali reopened this Sep 16, 2026
@cagataycali
cagataycali merged commit dcb62c2 into strands-labs:main Sep 16, 2026
17 of 19 checks passed
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.

2 participants