generated from coulomb/repo-seed
test: harden suite with error-path contracts + coverage floor (98%)
Adds tests/test_error_paths.py covering real failure contracts (red-link single() KeyError, unknown/unattached-shard apply_overlay, kernel.delete missing, conformance survives a broken profile, Placement str). Adds a [tool.coverage.report] fail_under=90 floor (engages on pytest --cov, not bare pytest). 76 tests, 98% coverage, pyflakes clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -36,6 +36,11 @@ pythonpath = ["src"]
|
|||||||
branch = true
|
branch = true
|
||||||
source = ["shard_wiki"]
|
source = ["shard_wiki"]
|
||||||
|
|
||||||
|
[tool.coverage.report]
|
||||||
|
show_missing = true
|
||||||
|
# Quality floor for `pytest --cov` / `coverage report` (not forced on a bare `pytest` run).
|
||||||
|
fail_under = 90
|
||||||
|
|
||||||
[tool.ruff]
|
[tool.ruff]
|
||||||
src = ["src", "tests"]
|
src = ["src", "tests"]
|
||||||
target-version = "py311"
|
target-version = "py311"
|
||||||
|
|||||||
76
tests/test_error_paths.py
Normal file
76
tests/test_error_paths.py
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
"""Error-path / contract tests across modules (keeps the suite honest about failure behaviour)."""
|
||||||
|
|
||||||
|
from collections.abc import Iterable
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from shard_wiki import InformationSpace
|
||||||
|
from shard_wiki.adapters import FolderAdapter, ShardAdapter, run_conformance
|
||||||
|
from shard_wiki.engine import EngineKernel
|
||||||
|
from shard_wiki.model import CapabilityProfile, Identity, Page, Placement
|
||||||
|
from shard_wiki.provenance import ProvenanceEnvelope
|
||||||
|
from shard_wiki.union import ResolutionKind, UnionGraph
|
||||||
|
|
||||||
|
|
||||||
|
def _folder(tmp_path, name, files, writable=False):
|
||||||
|
root = tmp_path / name
|
||||||
|
root.mkdir(parents=True, exist_ok=True)
|
||||||
|
for rel, text in files.items():
|
||||||
|
(root / rel).write_text(text, encoding="utf-8")
|
||||||
|
return FolderAdapter(name, root, writable=writable)
|
||||||
|
|
||||||
|
|
||||||
|
def test_resolution_single_on_red_link_raises():
|
||||||
|
u = UnionGraph("s")
|
||||||
|
res = u.resolve("ghost")
|
||||||
|
assert res.kind is ResolutionKind.RED_LINK
|
||||||
|
with pytest.raises(KeyError):
|
||||||
|
res.single()
|
||||||
|
|
||||||
|
|
||||||
|
def test_apply_unknown_overlay_raises(tmp_path):
|
||||||
|
space = InformationSpace("t")
|
||||||
|
space.attach(_folder(tmp_path, "w", {"Home.md": "x"}, writable=True))
|
||||||
|
with pytest.raises(KeyError):
|
||||||
|
space.apply_overlay("does-not-exist")
|
||||||
|
|
||||||
|
|
||||||
|
def test_apply_overlay_for_unattached_shard_raises(tmp_path):
|
||||||
|
space = InformationSpace("t")
|
||||||
|
space.attach(_folder(tmp_path, "w", {"Home.md": "x"}, writable=True))
|
||||||
|
# draft an overlay whose target shard is not attached -> apply can't find an adapter
|
||||||
|
ov = space.overlays.draft(Identity("ghost", "X"), "body", base_rev=None)
|
||||||
|
with pytest.raises(KeyError):
|
||||||
|
space.apply_overlay(ov.overlay_id)
|
||||||
|
|
||||||
|
|
||||||
|
def test_kernel_delete_missing_raises():
|
||||||
|
with pytest.raises(KeyError):
|
||||||
|
EngineKernel("eng").delete("nope")
|
||||||
|
|
||||||
|
|
||||||
|
def test_placement_str():
|
||||||
|
assert str(Placement("shardA", "sub/Page")) == "shardA/sub/Page"
|
||||||
|
|
||||||
|
|
||||||
|
class _BrokenProfileAdapter(ShardAdapter):
|
||||||
|
"""profile() raises — the conformance battery must report failure, not crash."""
|
||||||
|
|
||||||
|
@property
|
||||||
|
def shard_id(self) -> str:
|
||||||
|
return "broken"
|
||||||
|
|
||||||
|
def profile(self) -> CapabilityProfile:
|
||||||
|
raise RuntimeError("profile blew up")
|
||||||
|
|
||||||
|
def keys(self) -> Iterable[str]:
|
||||||
|
return []
|
||||||
|
|
||||||
|
def read(self, key: str) -> Page:
|
||||||
|
return Page(Identity("broken", key), "x", ProvenanceEnvelope(source_shard="broken"))
|
||||||
|
|
||||||
|
|
||||||
|
def test_conformance_survives_a_broken_profile():
|
||||||
|
report = run_conformance(_BrokenProfileAdapter())
|
||||||
|
assert not report.ok
|
||||||
|
assert any(c.name == "profile-validates" and not c.ok for c in report.checks)
|
||||||
Reference in New Issue
Block a user