Pin pytest below 9.2 for pytest-forked compatibility

Related to #788 (closed) (not Closes: the pin is a workaround and should be lifted once pytest-forked ships a fix).

TL;DR

  • Constrains the test dependency to pytest <9.2, which is incompatible with pytest-forked.
  • Without the pin, every test run with @pytest.mark.forked or --forked fails, including the whole PyTango suite.

Key Facts

  • Cause: pytest 9.2 turned TestReport.nodeid into a property backed by a NodeId dataclass. pytest-forked serialises the report by copying rep.__dict__ as is, so marshal.dumps in the forked child raises ValueError. The child catches it and calls os._exit(3) without a traceback, so the parent only reports EXITED with status 3. This is not a pytest bug; the NodeId change is intentional.
  • The failure is unconditional: passing, failing and skipped forked tests all fail the same way. Unforked tests are unaffected.
  • The constraint is applied in three independent places because they resolve dependencies separately: the tests extra in pyproject.toml, the pixi environment, and the micromamba install lines in the Linux CI. Jobs that install the tests extra from a built wheel are covered by pyproject.toml alone.
  • pixi.lock is unchanged: it already resolves pytest to a version below 9.2, so it still satisfies the new constraint and pixi will not re-solve.
  • The pin covers Windows too, via the tests extra, although Windows does not use --forked. Keeping one constraint across platforms avoids a split test matrix.
  • Downstream device servers are affected the same way when their tests follow the testing how-to and wrap DeviceTestContext in @pytest.mark.forked, hence the warning added to the documentation.

How to use

Reproduce the failure:

pip install "pytest==9.2.0" "pytest-forked==1.7.5"
import pytest

@pytest.mark.forked
def test_forked_passes():
    assert True

The test fails with running the test EXITED with status 3. With pytest <9.2 it passes.

Caveats

  • This is a workaround, not a fix. The pin should be lifted once pytest-forked releases a version that converts _id back to a nodeid string, as pytest's own _report_to_json() already does. A fix is proposed upstream in pytest-forked PR #112 but is not merged, and pytest-forked has not released since 1.7.5.
  • An alternative to pinning is patching pytest_forked.serialize_report in conftest.py. That was not taken here because it would only protect PyTango's own suite, not users who install the tests extra.
  • The pin keeps PyTango on an older pytest until upstream moves, so new pytest 9.2 features are unavailable and the constraint will propagate to anything depending on the tests extra.
  • Removing --forked from the default test options would avoid the problem for PyTango's own suite but not for downstream servers using the @pytest.mark.forked marker.

🤖 Generated with Claude Code

Edited by Yury Matveev

Merge request reports

Loading
Loading