feat(harness): P4 — custom-test ergonomics (rcust)
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
Placement RULE: discovery.custom_tests covers ONLY functional/ + playwright/ — the top-level test_*.py glob for recipe dirs is removed (top level is reserved for lifecycle overlays; zero in-repo users of top-level custom tests, verified by sweep). Lifecycle-name exclusion inside the subdirs stays as the double-run safety net. HC2 default-deny unchanged (repo-local custom now pinned via functional/ in the gate test). New conftest fixture op_state: parses $CCCI_OP_STATE_FILE (op context: versions, artifact paths), skipping with a clear reason when unset/absent/unparseable — overlay tests read op facts from the fixture instead of hand-parsing env (zero existing hand-parsers found; the fixture is the documented path forward). deps fixture landed in P2d. Unit tests: placement-rule discovery tests (top-level custom NOT discovered; functional/playwright are; misfiled lifecycle names excluded), op_state fixture contract (reads file / skips without env / skips on missing file), deps fixture attribute sugar. Verified on cc-ci: cc-ci-run -m pytest tests/unit -q -> 184 passed; scripts/lint.sh -> PASS.
This commit is contained in:
48
tests/unit/test_conftest_fixtures.py
Normal file
48
tests/unit/test_conftest_fixtures.py
Normal file
@ -0,0 +1,48 @@
|
||||
"""Unit tests for the shared conftest fixtures added/reshaped by the rcust restructure (P2d/P4):
|
||||
`op_state` (run-scoped op context from $CCCI_OP_STATE_FILE) and `deps` (consolidated dep creds
|
||||
with attribute sugar). Pure — exercised via request.getfixturevalue with env monkeypatched."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
def test_op_state_fixture_reads_file(tmp_path, monkeypatch, request):
|
||||
f = tmp_path / "op.json"
|
||||
f.write_text(json.dumps({"backup": {"snapshot_id": "abc123"}, "upgrade": {"head_ref": "h"}}))
|
||||
monkeypatch.setenv("CCCI_OP_STATE_FILE", str(f))
|
||||
st = request.getfixturevalue("op_state")
|
||||
assert st["backup"]["snapshot_id"] == "abc123"
|
||||
assert st["upgrade"]["head_ref"] == "h"
|
||||
|
||||
|
||||
def test_op_state_fixture_skips_without_env(monkeypatch, request):
|
||||
monkeypatch.delenv("CCCI_OP_STATE_FILE", raising=False)
|
||||
with pytest.raises(pytest.skip.Exception, match="orchestrator"):
|
||||
request.getfixturevalue("op_state")
|
||||
|
||||
|
||||
def test_op_state_fixture_skips_on_missing_file(tmp_path, monkeypatch, request):
|
||||
monkeypatch.setenv("CCCI_OP_STATE_FILE", str(tmp_path / "nope.json"))
|
||||
with pytest.raises(pytest.skip.Exception, match="missing"):
|
||||
request.getfixturevalue("op_state")
|
||||
|
||||
|
||||
def test_deps_fixture_entries_expose_attributes(tmp_path, monkeypatch, request):
|
||||
"""`deps` (session-scoped) coerces the run deps file into entries with .domain/.realm/...
|
||||
attribute sugar while keeping dict-style access (rcust P2d). Single test for the session-
|
||||
cached fixture (one instantiation)."""
|
||||
f = tmp_path / "deps.json"
|
||||
f.write_text(
|
||||
json.dumps(
|
||||
{"keycloak": {"recipe": "keycloak", "domain": "kc.x", "client_secret": "s3cret"}}
|
||||
)
|
||||
)
|
||||
monkeypatch.setenv("CCCI_DEPS_FILE", str(f))
|
||||
deps = request.getfixturevalue("deps")
|
||||
assert deps["keycloak"].domain == "kc.x"
|
||||
assert deps["keycloak"]["client_secret"] == "s3cret"
|
||||
with pytest.raises(AttributeError):
|
||||
_ = deps["keycloak"].not_a_field
|
||||
Reference in New Issue
Block a user