noteguard / tests /test_transform.py
Chaeyoon
Refactor to Gold-RAP structure: src/ package, tests/, docs/, data/, output/
84981a4
Raw
History Blame Contribute Delete
1.89 kB
"""Transforms: redaction tags, patient-consistent pseudonyms, valid fake NHS, date-shift."""
import re
from datetime import datetime
from src.recognisers import find_rule_spans, nhs_number_is_valid
from src.transform import (
PSEUDONYM,
REDACTION,
PseudonymVault,
_fake_nhs_number,
apply_transform,
)
def test_redaction_removes_value_and_tags():
text = "NHS 943 476 5919"
out, _ = apply_transform(text, find_rule_spans(text), REDACTION)
assert "[NHS number]" in out
assert "943 476 5919" not in out
def test_pseudonym_is_consistent():
v = PseudonymVault()
assert v.token_for("PERSON", "Smith, John") == v.token_for("PERSON", "Smith, John")
def test_fake_nhs_number_valid_and_stable():
n1 = _fake_nhs_number("943 476 5919")
n2 = _fake_nhs_number("943 476 5919")
assert n1 == n2
assert nhs_number_is_valid(n1)
def test_nino_surrogate_format():
import re
v = PseudonymVault()
nino = v.token_for("UK_NINO", "AB 12 34 56 C")
assert re.fullmatch(r"[A-Z]{2}\d{6}[A-D]", nino)
def test_vehicle_surrogate_format():
import re
v = PseudonymVault()
reg = v.token_for("UK_VEHICLE_REGISTRATION", "AB12 CDE")
assert re.fullmatch(r"[A-Z]{2}\d{2} [A-Z]{3}", reg)
def test_date_shift_is_consistent_per_patient():
# Only date-of-birth dates are treated as PII, so both need a DOB context. The
# per-patient offset is consistent, so the interval between them is preserved.
text = "DOB 12/03/1981 ... DOB 20/03/1981"
out, _ = apply_transform(text, find_rule_spans(text), PSEUDONYM, PseudonymVault(), person_id="p1")
assert "12/03/1981" not in out and "20/03/1981" not in out
dates = [datetime.strptime(d, "%d/%m/%Y") for d in re.findall(r"\d{2}/\d{2}/\d{4}", out)]
assert len(dates) == 2
assert (dates[1] - dates[0]).days == 8 # consistent offset preserves the interval