Ben Baker's installed-software collection, software delivery (run_script and
update_app), agentless adoption tool and command-queue hardening, with his
authorship preserved.
Reviewed before promotion. Fixed: the endpoints plugin tests were never collected
by pytest, the SBOM snapshot table's key would exhaust on MySQL, ingest did not
truncate two columns strict MySQL would reject, and update_app's version branch
pinned a digest for a file that route never serves. Agent packaging moved off
require_role('admin') onto a new endpoints.agentpackage permission.
Contract 0.27.0. Full suite 2231, frontend 314.
51 lines
2.1 KiB
Python
51 lines
2.1 KiB
Python
"""No test file may sit where pytest will not collect it.
|
|
|
|
pytest.ini sets `testpaths = tests`, so a test file anywhere else is never run
|
|
by `pytest` and never run in CI. It still passes review, still gets maintained,
|
|
and still reports nothing.
|
|
|
|
That is not hypothetical. plugins/endpoints/tests/test_plugin.py arrived with a
|
|
merge carrying 55 lines of delivery assertions and was collected ZERO times; run
|
|
directly, five of its tests failed. plugins/printedparts/tests/test_plugin.py had
|
|
been sitting uncollected for longer. Both are now under tests/.
|
|
|
|
The failure mode is the worst kind: the suite is green, the coverage is imaginary,
|
|
and the authorisation on a route can be deleted without anything going red.
|
|
"""
|
|
from pathlib import Path
|
|
|
|
REPO = Path(__file__).resolve().parents[1]
|
|
|
|
# Where pytest actually looks (pytest.ini: testpaths = tests).
|
|
COLLECTED = REPO / 'tests'
|
|
|
|
# Trees that legitimately hold test-shaped files pytest must not collect:
|
|
# vendored dependencies, build output, and the frontend's own vitest specs.
|
|
IGNORED = ('node_modules', 'venv', '.git', 'dist', '__pycache__',
|
|
'site-packages', '.plugins-staged', 'frontend')
|
|
|
|
# The Windows installer stages a whole copy of the app under here. It is build
|
|
# output, not source, and the export excludes it - caught by this test on its
|
|
# first run, which is the sort of thing the ignore list exists for.
|
|
IGNORED_TREES = ('deploy/windows/installer/bundle',)
|
|
|
|
|
|
def test_every_test_file_lives_where_pytest_looks():
|
|
stray = []
|
|
for path in REPO.rglob('test_*.py'):
|
|
if any(part in IGNORED for part in path.parts):
|
|
continue
|
|
relative = path.relative_to(REPO).as_posix()
|
|
if any(relative.startswith(tree) for tree in IGNORED_TREES):
|
|
continue
|
|
if COLLECTED in path.parents:
|
|
continue
|
|
stray.append(path.relative_to(REPO))
|
|
|
|
assert not stray, (
|
|
'These test files are never collected, because pytest.ini limits\n'
|
|
'collection to tests/. They pass review and report nothing:\n '
|
|
+ '\n '.join(str(p) for p in sorted(stray))
|
|
+ '\n\nMove them under tests/ (tests/test_plugins/ for plugin tests).'
|
|
)
|