RICS / backend /tests /test_report_postprocessor.py
StormShadow308's picture
Add demo documentation and Docker setup for v2 report generation system
aad7814
Raw
History Blame Contribute Delete
4.1 kB
"""Verification for the report post-processing pipeline (pure transform)."""
from __future__ import annotations
import re
import pytest
from backend.utils.report_postprocessor import (
_jaccard_similarity,
polish_report,
)
_RAW = (
"[REDACTED_NAME_1] repairs tend to be expensive due to the associated "
"scaffolding costs. SEE THE LIMITATIONS OF OUR INSPECTION ABOVE. MAIN ROOF:\n"
"The main roof structure is of hipped pitch and [[REDACTED_NAME_2]] "
"construction, partially extended to form\ndormers. The pitched roof covering "
"appears to be of plain concrete tiles. However, some areas were concealed "
"from view due to the loft\n2\nRICS Home Survey - Level 3\n26\nconversion. "
"Condition Rating 2. Condition Rating 2."
)
def test_raises_on_empty():
with pytest.raises(ValueError):
polish_report("")
with pytest.raises(ValueError):
polish_report(" \n ")
def test_pure_function_idempotent_on_clean_input():
out1 = polish_report(_RAW)
# Same input -> same output.
assert polish_report(_RAW) == out1
def test_orphan_page_numbers_removed_globally():
out = polish_report(_RAW)
assert not re.search(r"(?m)^\s*\d{1,3}\s*$", out)
assert "loft conversion" in out # sentence rejoined across the page break
def test_repeated_doc_header_suppressed():
out = polish_report(_RAW)
assert "RICS Home Survey" not in out
def test_sentence_initial_placeholder_grammar():
out = polish_report(_RAW)
assert out.startswith("Repairs tend to be expensive")
assert "REDACTED" not in out
def test_mid_sentence_placeholder_becomes_neutral():
out = polish_report(_RAW)
# Never the bare word "specified" — must be a visible, honest placeholder.
assert "specified" not in out.lower()
assert "[SURVEYOR TO CONFIRM] construction" in out
assert "REDACTED" not in out
def test_all_caps_directive_scrubbed():
out = polish_report(_RAW)
assert "SEE THE LIMITATIONS" not in out.upper()
def test_consecutive_duplicate_short_sentence_collapsed():
out = polish_report(_RAW)
assert out.count("Condition Rating 2.") == 1
def test_non_adjacent_short_repeats_preserved():
raw = (
"The flashing is defective. Condition Rating 2. "
"The gutter is blocked and overflowing at the rear. Condition Rating 2."
)
out = polish_report(raw)
assert out.count("Condition Rating 2.") == 2
def test_near_duplicate_paragraph_collapsed():
para = (
"The mortar bedding and pointing to the ridge and hip tiles is "
"deteriorating and repointing is required to prevent wind uplift damage."
)
raw = f"{para}\n\n{para}\n\nA distinct closing observation about the gutters."
out = polish_report(raw)
assert out.count("mortar bedding and pointing") == 1
assert "closing observation about the gutters" in out
def test_caps_word_in_normal_sentence_not_stripped():
raw = "Please see the limitations of our inspection in the relevant section."
out = polish_report(raw)
assert "limitations of our inspection" in out
def test_standalone_placeholder_line_removed():
raw = "Roof inspected from ground level.\n[REDACTED_ADDRESS_1]\nNo defects noted."
out = polish_report(raw)
assert "REDACTED" not in out
assert "Roof inspected from ground level." in out
assert "No defects noted." in out
def test_extra_header_patterns_are_firm_agnostic():
raw = "Roof comments here.\nACME SURVEYS LLP CONFIDENTIAL\nMore roof comments."
out = polish_report(
raw,
extra_header_patterns=[re.compile(r"ACME SURVEYS LLP CONFIDENTIAL")],
)
assert "ACME SURVEYS" not in out
def test_unicode_normalisation():
raw = "The roof\u2019s covering \u2013 slate \u2014 is sound\u00a0and intact."
out = polish_report(raw)
assert "\u2019" not in out and "\u2013" not in out and "\u2014" not in out
assert "\u00a0" not in out
def test_jaccard_bounds():
assert _jaccard_similarity("abcdef", "abcdef") == 1.0
assert _jaccard_similarity("abcdef", "xyzuvw") == 0.0