2026-10-02 11:52:43 +01:00
|
|
|
"""Parent-facing groups over GIAS establishment types and religious characters.
|
|
|
|
|
|
|
|
|
|
Every GIAS code must be accounted for, so a new DfE code fails here instead of
|
|
|
|
|
silently vanishing from the filter.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
from pathlib import Path
|
|
|
|
|
|
|
|
|
|
import numpy as np
|
|
|
|
|
import pytest
|
|
|
|
|
import yaml
|
|
|
|
|
|
|
|
|
|
from backend.gias_codes import RELIGIOUS_CHARACTER, SCHOOL_TYPE
|
|
|
|
|
from backend.school_groups import (
|
|
|
|
|
FAITH_GROUPS,
|
|
|
|
|
TYPE_GROUPS,
|
|
|
|
|
UNOFFERED_TYPE_CODES,
|
|
|
|
|
faith_groups_for,
|
|
|
|
|
type_group_for,
|
2026-10-02 15:51:35 +01:00
|
|
|
type_group_key,
|
2026-10-02 11:52:43 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
DBT_PROJECT = Path(__file__).resolve().parents[2] / "pipeline" / "transform" / "dbt_project.yml"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _non_england_codes() -> set[int]:
|
|
|
|
|
return set(yaml.safe_load(DBT_PROJECT.read_text())["vars"]["non_england_school_type_codes"])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_every_type_code_is_in_exactly_one_place():
|
|
|
|
|
places = [codes for _, _, codes in TYPE_GROUPS] + [UNOFFERED_TYPE_CODES, _non_england_codes()]
|
|
|
|
|
for code in SCHOOL_TYPE:
|
|
|
|
|
homes = sum(code in p for p in places)
|
|
|
|
|
assert homes == 1, f"type code {code} ({SCHOOL_TYPE[code]}) is in {homes} places"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_every_religion_code_has_a_faith():
|
|
|
|
|
for code, name in RELIGIOUS_CHARACTER.items():
|
|
|
|
|
assert any(code in codes for _, _, codes in FAITH_GROUPS), f"{code} {name!r}"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_type_groups_in_display_order():
|
|
|
|
|
assert [k for k, _, _ in TYPE_GROUPS] == [
|
2026-10-02 15:51:35 +01:00
|
|
|
"state", "independent", "special", "post16", "alternative"]
|
2026-10-02 11:52:43 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_faiths_in_display_order():
|
|
|
|
|
assert [k for k, _, _ in FAITH_GROUPS] == [
|
|
|
|
|
"none", "church_of_england", "roman_catholic", "other_christian",
|
|
|
|
|
"jewish", "muslim", "other_faith"]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.mark.parametrize("name, group", [
|
2026-10-02 15:51:35 +01:00
|
|
|
("Academy converter", "state"),
|
|
|
|
|
("University technical college", "state"),
|
|
|
|
|
("Voluntary aided school", "state"),
|
|
|
|
|
("Local authority nursery school", "state"),
|
2026-10-02 11:52:43 +01:00
|
|
|
("Other independent school", "independent"),
|
|
|
|
|
("Other independent special school", "special"),
|
|
|
|
|
("Special post 16 institution", "special"),
|
|
|
|
|
("Further education", "post16"),
|
|
|
|
|
("Pupil referral unit", "alternative"),
|
2026-10-02 15:51:35 +01:00
|
|
|
("academy CONVERTER", "state"),
|
2026-10-02 11:52:43 +01:00
|
|
|
])
|
|
|
|
|
def test_type_group_by_name(name, group):
|
|
|
|
|
assert type_group_for(name) == group
|
|
|
|
|
|
|
|
|
|
|
2026-10-02 15:51:35 +01:00
|
|
|
@pytest.mark.parametrize("value, key", [
|
|
|
|
|
("state", "state"),
|
|
|
|
|
("Special", "special"),
|
|
|
|
|
# The two state groups that preceded "state", kept so their links still work.
|
|
|
|
|
("academy", "state"),
|
|
|
|
|
("Council", "state"),
|
|
|
|
|
("Community school", None),
|
|
|
|
|
("", None),
|
|
|
|
|
])
|
|
|
|
|
def test_type_group_key_resolves_keys_and_old_keys(value, key):
|
|
|
|
|
assert type_group_key(value) == key
|
|
|
|
|
|
|
|
|
|
|
2026-10-02 11:52:43 +01:00
|
|
|
@pytest.mark.parametrize("name", [
|
|
|
|
|
"Higher education institutions", "Miscellaneous", "Unknown (9999)", "Academy", "", None, np.nan,
|
|
|
|
|
])
|
|
|
|
|
def test_unoffered_or_unknown_types_have_no_group(name):
|
|
|
|
|
assert type_group_for(name) is None
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.mark.parametrize("name, faiths", [
|
|
|
|
|
("Roman Catholic/Church of England", ("church_of_england", "roman_catholic")),
|
|
|
|
|
("Roman Catholic/Anglican", ("church_of_england", "roman_catholic")),
|
|
|
|
|
("Church of England/Methodist", ("church_of_england", "other_christian")),
|
|
|
|
|
("Church of England/Christian", ("church_of_england",)),
|
|
|
|
|
("Catholic", ("roman_catholic",)),
|
|
|
|
|
("Inter- / non- denominational", ("other_christian",)),
|
|
|
|
|
("Orthodox Jewish", ("jewish",)),
|
|
|
|
|
("Sunni Deobandi", ("muslim",)),
|
|
|
|
|
("Hindu", ("other_faith",)),
|
|
|
|
|
("Does not apply", ("none",)),
|
|
|
|
|
("None", ("none",)),
|
|
|
|
|
])
|
|
|
|
|
def test_faiths_by_name(name, faiths):
|
|
|
|
|
assert faith_groups_for(name) == faiths
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.mark.parametrize("missing", [None, np.nan, "", " "])
|
|
|
|
|
def test_a_missing_religion_is_no_religious_character(missing):
|
|
|
|
|
assert faith_groups_for(missing) == ("none",)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_an_unknown_religion_has_no_faith():
|
|
|
|
|
assert faith_groups_for("Unknown (77)") == ()
|