RICS / app /tests /test_notes_coverage.py
StormShadow308's picture
Speed up generation and ingestion; add live report progress on /status.
c893230
Raw
History Blame Contribute Delete
2.85 kB
"""Tests for notes-coverage guard.
These tests pin the deterministic behaviour of the coverage check that
``_generate_section_text`` and ``run_inspector_tool_loop`` use to decide
whether to regenerate. The whole point of the guard is to be reliable
without an LLM, so the assertions are exact thresholds, not loose bounds.
"""
from __future__ import annotations
from app.generator.notes_coverage import (
coverage_regenerate_hint,
coverage_report,
extract_bullet_facts,
)
def test_extract_bullet_facts_drops_stopword_only() -> None:
facts = extract_bullet_facts(["the and of"])
assert facts == []
def test_extract_bullet_facts_keeps_factish_tokens() -> None:
facts = extract_bullet_facts(["damp at rear elevation; postcode SW1A 1AA"])
assert len(facts) == 1
keys = facts[0].key_tokens
assert "damp" in keys
assert "rear" in keys
assert "elevation" in keys
assert "SW1A1AA" in keys
def test_coverage_report_full_match() -> None:
bullets = ["roof tiles slipped at south elevation"]
text = "Roof tiles slipped at the south elevation; replacement recommended."
rep = coverage_report(bullets, text)
assert rep.coverage_ratio == 1.0
assert rep.bullets_poorly_covered == 0
assert not rep.needs_regenerate
def test_coverage_report_detects_dropped_facts() -> None:
bullets = [
"boiler 22 years old, no service record",
"consumer unit lacks RCD protection on lighting circuits",
"rising damp at rear hallway",
]
text = "The property is generally well maintained."
rep = coverage_report(bullets, text)
assert rep.bullets_total == 3
assert rep.bullets_poorly_covered == 3
assert rep.coverage_ratio < 0.3
assert rep.needs_regenerate
hint = coverage_regenerate_hint(rep)
assert "COVERAGE VIOLATION" in hint
assert "boiler" in hint or "rcd" in hint.lower() or "damp" in hint.lower()
def test_coverage_report_stemming_does_not_misflag() -> None:
"""Bullet says 'cracks' but text says 'cracking' — should still cover."""
bullets = ["cracks to rear chimney stack"]
text = "Cracking observed to the rear chimney stack."
rep = coverage_report(bullets, text)
assert rep.coverage_ratio >= 0.7
def test_coverage_report_empty_bullets_safe() -> None:
rep = coverage_report([], "any text")
assert rep.bullets_total == 0
assert rep.coverage_ratio == 1.0
assert not rep.needs_regenerate
def test_coverage_regenerate_hint_lists_missing_tokens() -> None:
bullets = ["smoke alarm missing in hallway", "lead paint on window frames"]
text = "General property condition fair."
rep = coverage_report(bullets, text)
hint = coverage_regenerate_hint(rep)
assert "smoke" in hint.lower() or "alarm" in hint.lower()
assert "lead" in hint.lower() or "paint" in hint.lower()