Repository navigation
pytest.ini is dead config that silently shadows pyproject.toml (--strict-markers, testpaths, markers all inert) #130
Description
Activity
- addedP1-highRequired for production readinessRequired for production readinesstestingTest suite, CI, coverageTest suite, CI, coverage
on Aug 17, 2026 - added a parent issue
on Aug 17, 2026 - added a commit that references this issue
on Aug 17, 2026 Handoff plan written —
notes/handoff_130_pytest_config.md(commitde09f1a)A fresh session can pick this up cold. Everything in it was verified on
masterata9393b7; every fact carries the command that established it.⚠️ Landmine discovered while writing the planNaively fixing this breaks bare
pytestoutright. Verified:$ mv pytest.ini /tmp && pytest --co -q ERROR: Refusing to run 'tests/integration': tests/integration provisions real, billable cloud resources (AWS EKS/EC2). Set CLUSTRIX_ALLOW_BILLABLE=1 ...Cause:
master's pyproject setstestpaths = ["tests/unit", "tests/integration"], and pytest populatesconfig.argsfrom testpaths when no paths are given on the command line. The #109 guard inspectsconfig.args, so the moment pyproject becomes live, every bare run aborts.This is a trap I created in #109 and it must be defused first. The clean fix — verified — is to key the guard off
config.invocation_params.args(what the user actually typed) instead:invocation config.argsconfig.invocation_params.argspytest(testpaths live)['tests/unit', 'tests/integration'](no path entries) pytest tests/unit/['tests/unit/']['tests/unit/', ...flags]Corrections to this issue's original body
- pyproject declares 4 markers on
master(real_world,slow,unit,integration), not 13. The longer list I cited was from the closed epic branch.pytest.inideclares 14. master's pyprojectaddoptsis just-v --tb=short— no-n 4. So activating pyproject does not require xdist here. The xdist problem is specific to the epic branch, which deletespytest.ini. pip install -e ".[dev]" produces an environment where pytest cannot start #110 needs the same correction.
Measured marker gap (the thing that gates
--strict-markers)marker uses files declared in pyproject? real_world224 — yes dartmouth_network11 4 no slow6 — yes expensive5 5 no performance4 4 no integration2 — yes cleanup1 1 declared nowhere — test_kubernetes_performance_benchmarks.py:1038, likely a typoPlan shape
6 steps, one commit each, verification commands after every one:
- Baseline the numbers
- Defuse the landmine (guard →
invocation_params.args) — must be first - Delete
pytest.ini, settestpaths = ["tests"] - Declare the 3 missing markers; decide
cleanup - Enable
--strict-markerslast - Add a regression test so a stray config can never shadow again
- Full
scripts/pre_push_check.py, then correct pip install -e ".[dev]" produces an environment where pytest cannot start #110,MIGRATION.md:80,.claude/commands/testing/prime.md:95
The regression test uses
pytestconfig.inipathandgetini("markers"); both were verified against pytest 8.4.2 in the broken and fixed states, so the snippet is known-working rather than assumed. It fails today and passes after Step 2 — write it first and watch it fail.- pyproject declares 4 markers on
Fixed in #134 (branch
fix/130-pytest-config). Before/after evidence below; the issue closes when that PR merges.Before —
master@a9393b7$ head -1 pytest.ini [tool:pytest] $ pytest tests/unit/ --co 2>&1 | grep configfile configfile: pytest.ini $ pytest --markers | grep -c '^@pytest.mark.real_world' 0 $ printf 'import pytest\n@pytest.mark.bogus_xyz\ndef test_x(): assert True\n' > tests/unit/test_probe_tmp.py $ pytest tests/unit/test_probe_tmp.py --co -q 1 test collected # --strict-markers inert $ pytest tests/ -m "not real_world" --co -q -o addopts= | tail -1 1214/1592 tests collected (378 deselected), 6 errorsAfter
$ ls pytest.ini tox.ini setup.cfg 2>/dev/null | wc -l 0 $ pytest --co 2>&1 | grep configfile configfile: pyproject.toml $ pytest --markers | grep -cE '^@pytest.mark.(real_world|slow|unit|integration|expensive|dartmouth_network|performance):' 7 $ pytest tests/unit/test_probe_tmp.py --co -q ERROR ... Failed: 'bogus_xyz' not found in `markers` configuration option $ pytest --co -q | tail -1 1670 tests collected # bare pytest, 0 errors, no abort $ pytest tests/unit/ -q | tail -1 75 passedChecklist from this issue
- Decide on ONE config source — deleted
pytest.ini, keptpyproject.toml - Inventory every mark in use before activating — 7 in use, 4 were declared; added
expensive,dartmouth_network,performance; removed the single deadcleanup - Confirm
pytest-xdistis installed whereveraddoptsapplies — not needed:master'saddoptshas no-n. A comment aboveaddoptsnow records that adding one requires moving xdist from[test]into[dev]first (pip install -e ".[dev]" produces an environment where pytest cannot start #110) - Verify
testpathsactivation does not pulltests/real_world/into default runs — it does collect them (testpaths = ["tests"]), which is correct and matches the previous no-config behaviour. Nothing runs them by default: CI usespytest tests/unit/ -m "not real_world", andscripts/pre_push_check.pynow does the same, which it previously did not - Land
--strict-markerslast — Step 4, after the marker inventory was clean - Add a test asserting the config file is the expected one —
tests/unit/test_pytest_config.py, four assertions, all failing onmaster
Two corrections to this issue's own text
"13 markers" / "1,532 marker issues."
pytest.inideclared 10 markers andpyproject.toml4. The suite uses 7 distinct non-builtin markers across 253 applications. The 1,532 figure came fromscripts/test_discovery.pyon the closed epic branch and does not correspond to anything measurable onmaster.The landmine was not in the issue. Deleting
pytest.inialone breakspytestentirely, becausetestpathsthen feedsconfig.argsand the #109 guard refuses the run. That had to be fixed first, in its own commit. Details in #134 and innotes/handoff_130_pytest_config.md.Found along the way
- The Step 0 baseline had 6 collection errors, not zero: an f-string backslash
SyntaxError(fatal on Python <3.12 whilerequires-pythonis>=3.8) plus undeclarednumpy/pandas. Fixed here, since Step 4's gate is "0 errors". scripts/pre_push_check.pycannot exit 0 for unrelated reasons, and never could — filed as pre_push_check.py can never pass: 92 flake8 findings, incl. a real f-string bug in test_direct_gpu_detection.py #133, which also documents a real f-string bug intests/integration/test_direct_gpu_detection.py.- pip install -e ".[dev]" produces an environment where pytest cannot start #110's
addoptspremise and itssklearnclaim are both wrong; corrected there.
- Decide on ONE config source — deleted
- added a commit that references this issue
on Aug 17, 2026
Part of #108 · Phase 1 · Discovered while red-teaming #109.
Problem
pytest.iniuses the section header[tool:pytest]. That header is only valid insetup.cfg. In a file namedpytest.ini, pytest requires[pytest].pytest still selects the file as its config — and having selected it, stops looking, so
pyproject.toml's[tool.pytest.ini_options]is never read.Verified:
Everything currently inert
Both files declare these; neither takes effect:
addopts(-v --tb=short --strict-markers, and-n 4 --dist loadfilein pyproject)testpathstestspytestcollects the whole repomarkers(13 of them)filterwarnings--strict-markersWhy this matters beyond tidiness
pip install -e ".[dev]"cannot start pytest becauseaddoptsrequires xdist. That is true only on branches wherepytest.iniis absent — the epic branch deleted it. Onmaster,addoptsnever applies. Any statement about "the addopts" needs to say which config was live.pytest.mark.expensivetoday producesPytestUnknownMarkWarning, not a usable selector.--strict-markersbeing inert hides typos.scripts/test_discovery.py(on the closed epic branch) found 1,532 marker-hygiene issues that a live--strict-markerswould have caught at source.Fix — needs care, do not just flip it
The obvious change (
[tool:pytest]→[pytest], or deletepytest.iniso pyproject wins) will activate--strict-markers,testpaths, and possibly-n 4. Any test using an unregistered mark then becomes a hard error, and there are 1,532 known marker issues. Sequence it:pytest.ini, keeppyproject.toml(it has the fuller marker list — 13 vs 10 — and is the modern convention).grep -rhoE "@pytest\.mark\.[a-z_]+" tests/ | sort -uand reconcile against the registered list.pytest-xdistis installed whereveraddoptswill now apply (ties to pip install -e ".[dev]" produces an environment where pytest cannot start #110).testpathsactivation does not pulltests/real_world/into default runs.--strict-markerslast, once the marker inventory is clean.Config.inifileis the expected file, so a future stray config file cannot silently shadow it again.Verification