fix: testops_multi run_id handoff for pytest-xdist workers (pytest part)#499
Merged
Conversation
In testops_multi mode, the xdist controller's reporter produces a
{project_code: run_id} dict, but pytest_sessionstart wrote it via
str(self.run_id) and load_run_from_lock read it back as a single
positional string. Workers then crashed in
QaseTestOpsMulti.set_run_id() with
"missing 1 required positional argument: 'run_id'", silently fell
through the QaseCoreReporter fallback path, and dropped every result
into local JSON files instead of TestOps.
Serialise the run id via json.dumps in the controller and parse it
back with json.loads in load_run_from_lock; if the lock file is in the
legacy non-JSON shape (a bare numeric string from a previous run),
fall back to treating it as a scalar so single-project workers keep
working. Pass the parsed value through to
QaseCoreReporter.set_run_id(), which in commons 5.1.2 dispatches dict
input to QaseTestOpsMulti.set_run_ids() so every project is seeded in
each worker.
The xdist fix in plugin.py only works when paired with QaseTestOpsMulti.set_run_ids() and the dict-aware QaseCoreReporter.set_run_id() dispatch added in qase-python-commons 5.1.2. Pin the minimum so new installs of qase-pytest 8.3.1 never end up with the older commons release where workers would silently fall back to the local report.
The 3-day PIP_UPLOADED_PRIOR_TO quarantine in the matrix test job blocked cross-package PRs that depended on a freshly-published qase-python-commons release: pytest pinning qase-python-commons~=5.1.2 could not be installed for up to 72 hours after the commons release landed on PyPI, even though the package is published from this same repository's pipeline. Prefetch qase-python-commons, qase-api-client and qase-api-v2-client into a find-links cache with PIP_UPLOADED_PRIOR_TO unset, then export PIP_FIND_LINKS so subsequent pip invocations - including those tox spawns inside its venv - resolve those packages from the local cache. PIP_UPLOADED_PRIOR_TO operates on PyPI metadata (upload_time_iso_8601), which local wheels do not carry, so the find-links candidates are honoured even when the index-side filter would have removed them. External dependencies remain subject to the cutoff so the supply-chain hardening for third-party packages is unchanged.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Pytest-only half of the two-PR split. Companion to #498 (commons).
Important
Do not merge this PR until #498 is merged and
qase-python-commons5.1.2 is published to PyPI. This PR pinsqase-python-commons~=5.1.2and will not install otherwise.Symptom (customer report)
Running
pytest tests/examples/test_login.py -n 2 -sintestops_multimode:Workers crashed, silently fell back to the local report reporter, and dropped results from TestOps.
Root cause (pytest side)
QasePytestPlugin.pytest_sessionstart(controller branch) wrote the run id viastr(self.run_id). Intestops_multimodeself.run_idis adict, so the lock file held"{'DW': 1553}"— not round-trippable.QasePytestPlugin.load_run_from_lock(worker branch) read that string back and calledself.reporter.set_run_id(self.run_id)with one positional argument, which crashed inside the commons multi reporter.Fix in this PR
pytest_sessionstartnow writes the run id viajson.dumps, so the dict shape survives the controller → worker boundary.load_run_from_lockparses withjson.loads; the result is a dict in multi mode and a scalar (string) in single mode. Falls back to treating the raw read as a string if the file is in the legacy non-JSON format, so older lock files still load.QaseCoreReporter.set_run_id, which in commons 5.1.2 dispatchesdictinput toQaseTestOpsMulti.set_run_ids()(the companion change in fix: testops_multi xdist run_id handoff + mask api token in config log (commons part) #498).Dependency pin
Bumped
qase-python-commonsminimum from~=5.1.1to~=5.1.2inpyproject.toml. Without 5.1.2, the dict reaches the commons reporter without a matchingset_run_ids()method and the fix is silently dead.Test plan
examples/multiproject/pytestwithpytest -n 2:main: 4×missing 1 required positional argumenterrors, 4 silent fallback JSON files.DEVX #895/DEMO #714.Release
qase-pytest8.3.0 → 8.3.1.qase-python-commons~=5.1.2so new installs always pull the matching commons release.Companion PR