a b/tests/unit/test_tables.py
1
import re
2
3
import pytest
4
5
import ehrql.tables
6
from ehrql.query_language import get_tables_from_namespace
7
from ehrql.tables import Constraint, tpp
8
from ehrql.utils.module_utils import get_submodules
9
10
11
@pytest.mark.parametrize("module", list(get_submodules(ehrql.tables)))
12
def test___all__(module):
13
    table_names = {name for name, _ in get_tables_from_namespace(module)}
14
    if not table_names:
15
        pytest.skip(f"{module.__name__} has no tables")
16
    assert module.__all__ == sorted(module.__all__)
17
    assert table_names == set(module.__all__)
18
19
20
valid_examples_for_regex_constraints = [
21
    (tpp.addresses, "msoa_code", "E02012345"),
22
    (tpp.ec, "sus_hrg_code", "AA00A"),
23
    (tpp.opa, "hrg_code", "AA00A"),
24
    (tpp.practice_registrations, "practice_stp", "E54000012"),
25
    (tpp.wl_clockstops, "activity_treatment_function_code", "AB1"),
26
    (tpp.wl_openpathways, "activity_treatment_function_code", "AB1"),
27
    (tpp.wl_openpathways, "source_of_referral", "A1"),
28
]
29
30
invalid_examples_for_regex_constraints = [
31
    (tpp.addresses, "msoa_code", "X02012345"),
32
    (tpp.ec, "sus_hrg_code", "AA000A"),
33
    (tpp.opa, "hrg_code", "AA000A"),
34
    (tpp.practice_registrations, "practice_stp", "X54000012"),
35
    (tpp.wl_clockstops, "activity_treatment_function_code", "AB10"),
36
    (tpp.wl_openpathways, "activity_treatment_function_code", "AB10"),
37
    (tpp.wl_openpathways, "source_of_referral", "A10"),
38
]
39
40
41
@pytest.mark.parametrize(
42
    "table,column_name,example", valid_examples_for_regex_constraints
43
)
44
def test_regex_constraints_match_valid_examples(table, column_name, example):
45
    regex = get_regex_constraint(table, column_name)
46
    assert bool(re.fullmatch(regex, example))
47
48
49
@pytest.mark.parametrize(
50
    "table,column_name,example", invalid_examples_for_regex_constraints
51
)
52
def test_regex_constraints_do_not_match_invalid_examples(table, column_name, example):
53
    regex = get_regex_constraint(table, column_name)
54
    assert not bool(re.fullmatch(regex, example))
55
56
57
@pytest.mark.parametrize(
58
    "examples",
59
    [valid_examples_for_regex_constraints, invalid_examples_for_regex_constraints],
60
)
61
def test_all_regex_constraints_are_tested(examples):
62
    tables = {
63
        table
64
        for module in get_submodules(ehrql.tables)
65
        for _, table in get_tables_from_namespace(module)
66
    }
67
    tables_column_names = {
68
        (table, column_name)
69
        for table in tables
70
        for column_name in table._qm_node.schema.column_names
71
        if get_regex_constraint(table, column_name)
72
    }
73
74
    assert tables_column_names == {
75
        (table, column_name) for table, column_name, _ in examples
76
    }
77
78
79
def get_regex_constraint(table, column_name):
80
    schema = table._qm_node.schema
81
    constraint = schema.get_column_constraint_by_type(column_name, Constraint.Regex)
82
    return getattr(constraint, "regex", None)