feat: GIAS code->name dictionaries generated from live bulk CSV
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
"""Tests for the GIAS code->name dictionaries (spec 2026-07-09).
|
||||
|
||||
The dictionaries are generated from the live GIAS bulk CSV by
|
||||
pipeline/scripts/generate_gias_codes.py — these tests assert the module's
|
||||
contract, key sentinel values the marts/UI depend on, and that the pipeline
|
||||
copy has not drifted from the canonical backend module.
|
||||
"""
|
||||
|
||||
import math
|
||||
from pathlib import Path
|
||||
|
||||
from backend.gias_codes import (
|
||||
ADMISSIONS_POLICY,
|
||||
ESTABLISHMENT_STATUS,
|
||||
OFFICIAL_SIXTH_FORM,
|
||||
PHASE_OF_EDUCATION,
|
||||
RELIGIOUS_CHARACTER,
|
||||
SCHOOL_TYPE,
|
||||
translate,
|
||||
)
|
||||
|
||||
REPO = Path(__file__).resolve().parents[2]
|
||||
|
||||
|
||||
def test_translate_known_code():
|
||||
open_code = next(c for c, n in ESTABLISHMENT_STATUS.items() if n == "Open")
|
||||
assert translate(open_code, ESTABLISHMENT_STATUS) == "Open"
|
||||
|
||||
|
||||
def test_translate_unknown_code_degrades_gracefully():
|
||||
assert translate(9999, ESTABLISHMENT_STATUS) == "Unknown (9999)"
|
||||
|
||||
|
||||
def test_translate_none_and_nan_return_none():
|
||||
assert translate(None, ESTABLISHMENT_STATUS) is None
|
||||
assert translate(float("nan"), ESTABLISHMENT_STATUS) is None
|
||||
|
||||
|
||||
def test_translate_accepts_float_codes():
|
||||
# pd.read_sql yields float columns when NULLs are present
|
||||
open_code = next(c for c, n in ESTABLISHMENT_STATUS.items() if n == "Open")
|
||||
assert translate(float(open_code), ESTABLISHMENT_STATUS) == "Open"
|
||||
|
||||
|
||||
def test_sentinel_names_present():
|
||||
"""Names the marts/UI compare against must exist verbatim."""
|
||||
assert "Open" in ESTABLISHMENT_STATUS.values()
|
||||
assert "Open, but proposed to close" in ESTABLISHMENT_STATUS.values()
|
||||
assert "Has a sixth form" in OFFICIAL_SIXTH_FORM.values()
|
||||
assert "Primary" in PHASE_OF_EDUCATION.values()
|
||||
assert "Secondary" in PHASE_OF_EDUCATION.values()
|
||||
assert "Does not apply" in RELIGIOUS_CHARACTER.values()
|
||||
assert all(len(d) > 0 for d in (
|
||||
SCHOOL_TYPE, ESTABLISHMENT_STATUS, PHASE_OF_EDUCATION,
|
||||
OFFICIAL_SIXTH_FORM, RELIGIOUS_CHARACTER, ADMISSIONS_POLICY,
|
||||
))
|
||||
|
||||
|
||||
def test_pipeline_copy_is_identical():
|
||||
canonical = (REPO / "backend" / "gias_codes.py").read_text()
|
||||
copy = (REPO / "pipeline" / "scripts" / "gias_codes.py").read_text()
|
||||
assert canonical == copy, (
|
||||
"pipeline/scripts/gias_codes.py has drifted from backend/gias_codes.py — "
|
||||
"regenerate with pipeline/scripts/generate_gias_codes.py and copy the file"
|
||||
)
|
||||
|
||||
|
||||
def test_seed_matches_dictionaries():
|
||||
import csv
|
||||
fields = {
|
||||
"school_type": SCHOOL_TYPE,
|
||||
"establishment_status": ESTABLISHMENT_STATUS,
|
||||
"phase_of_education": PHASE_OF_EDUCATION,
|
||||
"official_sixth_form": OFFICIAL_SIXTH_FORM,
|
||||
"religious_character": RELIGIOUS_CHARACTER,
|
||||
"admissions_policy": ADMISSIONS_POLICY,
|
||||
}
|
||||
seed_path = REPO / "pipeline" / "transform" / "seeds" / "gias_code_names.csv"
|
||||
seed: dict[str, dict[int, str]] = {k: {} for k in fields}
|
||||
with open(seed_path, newline="") as fh:
|
||||
for row in csv.DictReader(fh):
|
||||
seed[row["field"]][int(row["code"])] = row["name"]
|
||||
assert seed == fields
|
||||
Reference in New Issue
Block a user