aucourt-ingest/tests/test_outcome_parser.py
slothitude d77fe12cfc AuCourtIngest: complete 8-stage Australian legal case ingestion pipeline
Source layer (5 court sources), processing pipeline (parse/extract/chunk/embed/graph),
property graph with 8 node types, juror subgraph queries with 6 personas,
orchestrator with bootstrap/watch/backfill/audit/process modes, 170 tests.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-30 11:56:23 +10:00

117 lines
4.1 KiB
Python

"""Tests for OutcomeParser."""
import json
import pytest
from aucourt_ingest.processing.outcome_parser import OutcomeParser, VALID_VERDICTS
@pytest.fixture
def parser():
return OutcomeParser()
class TestHeadnotePattern:
def test_held_conviction_quashed(self, parser):
text = "HELD: conviction quashed. The appeal is allowed."
result = parser.parse(text)
assert result["verdict"] == "conviction_quashed"
assert result["resolution_method"] == "held"
def test_held_acquittal(self, parser):
text = "HELD: the accused is acquitted of all charges."
result = parser.parse(text)
assert result["verdict"] == "not_guilty"
class TestAppealPatterns:
def test_appeal_allowed(self, parser):
text = "The Court orders that the appeal is allowed."
result = parser.parse(text)
assert result["verdict"] == "appeal_allowed"
def test_appeal_dismissed(self, parser):
text = "The appeal is dismissed."
result = parser.parse(text)
assert result["verdict"] == "appeal_dismissed"
def test_convictions_quashed(self, parser):
text = "Appeal allowed. Convictions on counts 1 and 3 are quashed."
result = parser.parse(text)
# "Appeal allowed" matches first — this is correct priority behavior
assert result["verdict"] == "appeal_allowed"
def test_set_aside(self, parser):
text = "The convictions are set aside."
result = parser.parse(text)
assert result["verdict"] == "conviction_quashed"
class TestGuiltyNotGuiltyPatterns:
def test_guilty(self, parser):
text = "The jury returns a verdict of guilty on the charge of murder."
result = parser.parse(text)
assert result["verdict"] == "guilty"
def test_not_guilty(self, parser):
text = "The jury returns a verdict of not guilty."
result = parser.parse(text)
assert result["verdict"] == "not_guilty"
def test_found_guilty(self, parser):
text = "The Court found the accused guilty."
result = parser.parse(text)
assert result["verdict"] == "guilty"
class TestHungJury:
def test_hung_jury(self, parser):
text = "After three days of deliberation, the jury was unable to reach a verdict and was discharged."
result = parser.parse(text)
assert result["verdict"] == "hung"
class TestSentenceExtraction:
def test_sentence_found(self, parser):
text = "I sentence the offender to imprisonment for 25 years."
result = parser.parse(text)
assert result["sentence"] is not None
assert "25" in result["sentence"]
class TestExonerationSources:
def test_exoneration_lookup(self, tmp_path):
exon_data = {"john smith_2015": {"verdict": "conviction_quashed", "notes": "Wrongful conviction"}}
p = tmp_path / "exoneration.json"
p.write_text(json.dumps(exon_data))
parser = OutcomeParser()
parser.load_exoneration_sources(p)
result = parser.parse("some text", case_name="John Smith", year=2015)
assert result["verdict"] == "conviction_quashed"
assert result["resolution_method"] == "exoneration"
class TestAppealCrossReference:
def test_appeal_allowed_updates_original(self, parser):
updated = parser.apply_appeal_cross_reference("guilty", "appeal_allowed")
assert updated == "conviction_quashed"
def test_appeal_dismissed_keeps_original(self, parser):
updated = parser.apply_appeal_cross_reference("guilty", "appeal_dismissed")
assert updated == "guilty"
def test_no_appeal_keeps_original(self, parser):
updated = parser.apply_appeal_cross_reference("not_guilty", None)
assert updated == "not_guilty"
class TestNoMatch:
def test_no_verdict_found(self, parser):
text = "The Court heard submissions from both parties regarding procedural matters."
result = parser.parse(text)
assert result["verdict"] is None
assert result["resolution_method"] is None
def test_empty_text(self, parser):
result = parser.parse("")
assert result["verdict"] is None