fix: Testisolation - kb_dir repointet config.ROOT, lint loest Kollektionen gegen den uebergebenen Baum auf (4.1.1, #44)
Files changed: - CHANGES.md - VERSION - instructions/dev/testing-conventions.md - tools/chemenu/lint_core.py - tools/chemenu/tests/conftest.py - tools/chemenu/tests/test_hermetic_env.py - tools/chemenu/tests/test_lint.py
This commit is contained in:
@@ -15,7 +15,6 @@ from chemenu.commands.lint import (
|
||||
)
|
||||
from chemenu.frontmatter_io import write_page
|
||||
from chemenu.provenance import cite_id, render_cite_block
|
||||
from chemenu.tests.conftest import use_shipped_type_specs
|
||||
from chemenu.version import Version
|
||||
|
||||
|
||||
@@ -482,26 +481,18 @@ def test_lint_does_not_count_a_shell_prompt_as_a_quote(kb_dir):
|
||||
|
||||
# --- the migration gate on `unlabelled_edges` / `unauthorised_labels` -------
|
||||
#
|
||||
# These four repoint `config.ROOT` at the fixture tree, which the `kb_dir`
|
||||
# fixture alone does not do. Two things need it: `write_kb_state()` writes
|
||||
# `.wikitool-kb.json` relative to `ROOT`, and `lint`'s collection lookup
|
||||
# resolves a page against `config.KB_DIR` rather than against the directory it
|
||||
# was handed - so without the repoint the gate would be read off the real
|
||||
# repository's state file.
|
||||
# These read and write `.wikitool-kb.json`, which `kb_state` resolves relative
|
||||
# to `config.ROOT`. The `kb_dir` fixture repoints `ROOT` at its own tmp_path
|
||||
# (Gitea #44), so the gate is read off the fixture tree; before it did, these
|
||||
# four ran against the real repository's state file and one of them overwrote
|
||||
# it.
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def rooted_kb(kb_dir, tmp_path, monkeypatch):
|
||||
monkeypatch.setattr(config, "ROOT", tmp_path)
|
||||
use_shipped_type_specs(monkeypatch)
|
||||
return kb_dir
|
||||
|
||||
|
||||
def _page_with_an_unlabelled_edge(rooted_kb):
|
||||
def _page_with_an_unlabelled_edge(kb_dir):
|
||||
"""A `related:` entry that is a bare title rather than a `label: title`
|
||||
mapping - the shape every page was in before the 4.0.0 migration."""
|
||||
write_page(
|
||||
rooted_kb / "entities/tools/bare-edge.md",
|
||||
kb_dir / "entities/tools/bare-edge.md",
|
||||
{"type": "types/entity.md", "entity_type": "tool", "tags": [], "created": "2026-09-03",
|
||||
"modified": "2026-09-03", "related": ["Modbus"], "sources": [], "confidence": 0.8,
|
||||
"provenance": "general", "summary": "One edge whose label was never declared."},
|
||||
@@ -509,14 +500,14 @@ def _page_with_an_unlabelled_edge(rooted_kb):
|
||||
)
|
||||
|
||||
|
||||
def test_unlabelled_edge_is_advisory_below_kb_version_4(rooted_kb):
|
||||
def test_unlabelled_edge_is_advisory_below_kb_version_4(kb_dir):
|
||||
"""The window the migration document describes: the machinery has landed,
|
||||
the corpus has not been converted yet, and `lint --fail-on-error` must not
|
||||
refuse the very tree the migration tells the instance to publish unit by
|
||||
unit."""
|
||||
_page_with_an_unlabelled_edge(rooted_kb)
|
||||
_page_with_an_unlabelled_edge(kb_dir)
|
||||
kb_state.write_kb_state(Version(3, 0, 0), [])
|
||||
report = run_lint(rooted_kb)
|
||||
report = run_lint(kb_dir)
|
||||
assert report["unlabelled_edges"] != []
|
||||
assert "unlabelled_edges" not in hard_error_keys()
|
||||
# Narrowed to the finding under test: the fixture corpus carries unrelated
|
||||
@@ -525,34 +516,64 @@ def test_unlabelled_edge_is_advisory_below_kb_version_4(rooted_kb):
|
||||
assert has_hard_errors({"unlabelled_edges": report["unlabelled_edges"]}) is False
|
||||
|
||||
|
||||
def test_unlabelled_edge_is_hard_at_kb_version_4(rooted_kb):
|
||||
def test_unlabelled_edge_is_hard_at_kb_version_4(kb_dir):
|
||||
"""Once the migration is recorded, a bare title is no longer a page waiting
|
||||
its turn - it is an edge whose author did not say what it asserts."""
|
||||
_page_with_an_unlabelled_edge(rooted_kb)
|
||||
_page_with_an_unlabelled_edge(kb_dir)
|
||||
kb_state.write_kb_state(Version(4, 0, 0), [])
|
||||
report = run_lint(rooted_kb)
|
||||
report = run_lint(kb_dir)
|
||||
assert report["unlabelled_edges"] != []
|
||||
assert "unlabelled_edges" in hard_error_keys()
|
||||
assert has_hard_errors({"unlabelled_edges": report["unlabelled_edges"]}) is True
|
||||
|
||||
|
||||
def test_unauthorised_label_is_hard_at_kb_version_4(rooted_kb):
|
||||
def test_unauthorised_label_is_hard_at_kb_version_4(kb_dir):
|
||||
"""The fixture contracts authorise `depends-on` but not `contradicts`."""
|
||||
write_page(
|
||||
rooted_kb / "entities/tools/off-menu.md",
|
||||
kb_dir / "entities/tools/off-menu.md",
|
||||
{"type": "types/entity.md", "entity_type": "tool", "tags": [], "created": "2026-09-03",
|
||||
"modified": "2026-09-03", "related": [{"contradicts": "Modbus"}], "sources": [],
|
||||
"confidence": 0.8, "provenance": "general", "summary": "A label off this menu."},
|
||||
"\n# off-menu\n\nA label the source collection never authorised.\n",
|
||||
)
|
||||
kb_state.write_kb_state(Version(4, 0, 0), [])
|
||||
report = run_lint(rooted_kb)
|
||||
report = run_lint(kb_dir)
|
||||
assert report["unauthorised_labels"] != []
|
||||
assert "unauthorised_labels" in hard_error_keys()
|
||||
assert has_hard_errors({"unauthorised_labels": report["unauthorised_labels"]}) is True
|
||||
|
||||
|
||||
def test_a_tree_that_never_declared_a_kb_version_keeps_every_key(rooted_kb):
|
||||
def test_unauthorised_label_is_judged_in_a_tree_that_is_not_the_configured_kb(
|
||||
kb_dir, tmp_path, monkeypatch
|
||||
):
|
||||
"""`run_lint()` judges the tree it was handed, not the configured corpus.
|
||||
|
||||
The collection lookup used to resolve a page against `config.KB_DIR`; a
|
||||
page anywhere else raised `ValueError`, read back as "no collection", and
|
||||
the label check skipped the edge without a word. That is why
|
||||
`unauthorised_labels` was untested in practice before Gitea #44 - every
|
||||
fixture tree was somewhere else. Here `ROOT` deliberately points away from
|
||||
the tree under lint, which is the case the old code got wrong.
|
||||
"""
|
||||
write_page(
|
||||
kb_dir / "entities/tools/off-menu.md",
|
||||
{"type": "types/entity.md", "entity_type": "tool", "tags": [], "created": "2026-09-03",
|
||||
"modified": "2026-09-03", "related": [{"contradicts": "Modbus"}], "sources": [],
|
||||
"confidence": 0.8, "provenance": "general", "summary": "A label off this menu."},
|
||||
"\n# off-menu\n\nA label the source collection never authorised.\n",
|
||||
)
|
||||
elsewhere = tmp_path / "elsewhere"
|
||||
elsewhere.mkdir()
|
||||
monkeypatch.setattr(config, "ROOT", elsewhere)
|
||||
assert config.KB_DIR != kb_dir
|
||||
|
||||
report = run_lint(kb_dir)
|
||||
assert {
|
||||
"page": "off-menu", "target": "Modbus", "label": "contradicts", "destination": "concepts"
|
||||
} in report["unauthorised_labels"]
|
||||
|
||||
|
||||
def test_a_tree_that_never_declared_a_kb_version_keeps_every_key(kb_dir):
|
||||
"""No `.wikitool-kb.json` means a fresh instance, which starts at the
|
||||
current shape rather than migrating into it - so there is no outstanding
|
||||
migration for a gated finding to be the noise of."""
|
||||
|
||||
Reference in New Issue
Block a user