add test coverage for CMS table models, CMS logging, and CCW tables/docs
All checks were successful
ci/woodpecker/push/infra-ci Pipeline was successful
ci/woodpecker/push/deploy Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful

3946 new tests covering:
- cms.table: all 150 SQLTable models (schema, tablename, qualified_name,
  column_names, nullable fields, construction, uniqueness)
- cms.log: JsonlHandler, setup() idempotency, custom attrs, exceptions
- ccw.table: all 41 claim tables across 7 types (IP, SNF, Hospice, HHA,
  HOP, Carrier, DME) with structural validation
- ccw.docs: all 308 variable documentation modules (importability,
  required attrs, type validation)
This commit is contained in:
kert
2026-02-28 20:44:53 -05:00
parent 68acc1edb3
commit 8b33613910
5 changed files with 631 additions and 0 deletions

0
tests/ccw/__init__.py Normal file
View File

109
tests/ccw/test_docs.py Normal file
View File

@@ -0,0 +1,109 @@
"""Tests for CCW FFS Claims Codebook variable documentation.
Validates that all 308 auto-generated variable modules have
consistent structure and required attributes.
"""
from __future__ import annotations
import importlib
import pytest
from ccw.docs import VARIABLES
# ── VARIABLES registry ───────────────────────────────────────────
class TestVariablesRegistry:
def test_variables_is_list(self) -> None:
assert isinstance(VARIABLES, list)
def test_variables_count(self) -> None:
assert len(VARIABLES) == 308
def test_at_most_one_duplicate(self) -> None:
# rndrng_physn_upin appears twice in the PDF codebook
unique = set(VARIABLES)
assert len(VARIABLES) - len(unique) <= 1
def test_all_lowercase(self) -> None:
for v in VARIABLES:
assert v == v.lower(), f"{v} is not lowercase"
# ── Module importability ─────────────────────────────────────────
class TestImportability:
@pytest.fixture(params=VARIABLES)
def var_module(self, request):
return importlib.import_module(f"ccw.docs.{request.param}")
def test_importable(self, var_module) -> None:
assert var_module is not None
# ── Required attributes ──────────────────────────────────────────
REQUIRED_ATTRS = ["name", "label", "type", "length", "source"]
VALID_TYPES = {"CHAR", "NUM", "DATE"}
class TestAttributes:
@pytest.fixture(params=VARIABLES)
def var_module(self, request):
return importlib.import_module(f"ccw.docs.{request.param}")
@pytest.mark.parametrize("attr", REQUIRED_ATTRS)
def test_has_required_attr(self, var_module, attr) -> None:
assert hasattr(var_module, attr), f"{var_module.__name__} missing '{attr}'"
def test_name_starts_uppercase(self, var_module) -> None:
# Most names are fully uppercase; a few have mixed-case
# parenthetical qualifiers (e.g. "PRVDR_NUM (Institutional claim)")
base = var_module.name.split("(")[0].strip()
assert base == base.upper()
def test_type_is_valid(self, var_module) -> None:
assert var_module.type in VALID_TYPES, (
f"{var_module.__name__}: type={var_module.type!r} not in {VALID_TYPES}"
)
def test_label_non_empty(self, var_module) -> None:
assert len(var_module.label) > 0
def test_length_is_numeric_string(self, var_module) -> None:
assert var_module.length.isdigit(), (
f"{var_module.__name__}: length={var_module.length!r} not numeric"
)
# ── Spot checks ──────────────────────────────────────────────────
class TestSpotChecks:
def test_bene_id(self) -> None:
mod = importlib.import_module("ccw.docs.bene_id")
assert mod.name == "BENE_ID"
assert mod.label == "Encrypted CCW Beneficiary ID"
assert mod.type == "CHAR"
assert mod.length == "15"
assert mod.source == "CCW"
def test_numeric_variable(self) -> None:
mod = importlib.import_module("ccw.docs.nch_prmry_pyr_clm_pd_amt")
assert mod.name == "NCH_PRMRY_PYR_CLM_PD_AMT"
assert mod.type == "NUM"
assert mod.short_name == "PRPAYAMT"
def test_has_short_and_long_name(self) -> None:
mod = importlib.import_module("ccw.docs.bene_id")
assert hasattr(mod, "short_name")
assert hasattr(mod, "long_name")
def test_docstring_present(self) -> None:
mod = importlib.import_module("ccw.docs.bene_id")
assert mod.__doc__ is not None
assert "BENE_ID" in mod.__doc__

221
tests/ccw/test_table.py Normal file
View File

@@ -0,0 +1,221 @@
"""Tests for CCW FFS Claims table models.
Validates that all 41 auto-generated Pydantic table models across
7 claim types (IP, SNF, Hospice, HHA, HOP, Carrier, DME) follow
the SQLTable contract.
"""
from __future__ import annotations
import inspect
from datetime import date
import pytest
from aco.table.base import SQLTable
from ccw.table import carrier, dme, hha, hop, hospice, ip, snf
def _all_ccw_classes():
"""Collect all SQLTable subclasses from all CCW table modules."""
classes = []
for mod in [carrier, dme, hha, hop, hospice, ip, snf]:
for name, cls in inspect.getmembers(mod, inspect.isclass):
if issubclass(cls, SQLTable) and cls is not SQLTable:
classes.append(cls)
return classes
ALL_CCW_CLASSES = _all_ccw_classes()
ALL_CCW_IDS = [cls.__name__ for cls in ALL_CCW_CLASSES]
# ── Module importability ─────────────────────────────────────────
class TestImports:
def test_all_seven_modules_import(self) -> None:
pass
def test_total_class_count(self) -> None:
assert len(ALL_CCW_CLASSES) == 41
# ── Schema metadata (parametrized across all 41 classes) ─────────
class TestSchemaMetadata:
@pytest.fixture(params=ALL_CCW_CLASSES, ids=ALL_CCW_IDS)
def table_cls(self, request):
return request.param
def test_schema_is_ccw(self, table_cls) -> None:
assert table_cls.__schema__ == "ccw"
def test_tablename_set(self, table_cls) -> None:
assert table_cls.__tablename__, f"{table_cls.__name__} empty tablename"
def test_qualified_name(self, table_cls) -> None:
assert table_cls.qualified_name() == f"ccw.{table_cls.__tablename__}"
def test_column_names_non_empty(self, table_cls) -> None:
assert len(table_cls.column_names()) > 0
def test_all_fields_nullable(self, table_cls) -> None:
for field_name, field_info in table_cls.model_fields.items():
assert field_info.default is None, (
f"{table_cls.__name__}.{field_name} not nullable"
)
# ── Claim type structure ─────────────────────────────────────────
class TestClaimTypeStructure:
"""Institutional claim types (IP, SNF, Hospice, HHA, HOP) have 7
sub-tables each; professional types (Carrier, DME) have 3 each."""
@pytest.mark.parametrize(
"mod,expected",
[
(ip, 7),
(snf, 7),
(hospice, 7),
(hha, 7),
(hop, 7),
(carrier, 3),
(dme, 3),
],
)
def test_subtable_count(self, mod, expected) -> None:
classes = [
c
for _, c in inspect.getmembers(mod, inspect.isclass)
if issubclass(c, SQLTable) and c is not SQLTable
]
assert len(classes) == expected
@pytest.mark.parametrize(
"mod,prefix",
[
(ip, "Ip"),
(snf, "Snf"),
(hospice, "Hospice"),
(hha, "Hha"),
(hop, "Hop"),
],
)
def test_institutional_subtable_names(self, mod, prefix) -> None:
"""Each institutional claim type has Base, RevenueCenter,
ConditionCode, OccurrenceCode, SpanCode, ValueCode, Demo."""
expected = {
f"{prefix}Base",
f"{prefix}RevenueCenter",
f"{prefix}ConditionCode",
f"{prefix}OccurrenceCode",
f"{prefix}SpanCode",
f"{prefix}ValueCode",
f"{prefix}Demo",
}
actual = {
name
for name, cls in inspect.getmembers(mod, inspect.isclass)
if issubclass(cls, SQLTable) and cls is not SQLTable
}
assert actual == expected
@pytest.mark.parametrize("mod,prefix", [(carrier, "Carrier"), (dme, "Dme")])
def test_professional_subtable_names(self, mod, prefix) -> None:
expected = {f"{prefix}Base", f"{prefix}Line", f"{prefix}Demo"}
actual = {
name
for name, cls in inspect.getmembers(mod, inspect.isclass)
if issubclass(cls, SQLTable) and cls is not SQLTable
}
assert actual == expected
# ── Tablename uniqueness ─────────────────────────────────────────
class TestUniqueness:
def test_no_duplicate_tablenames(self) -> None:
names = [cls.__tablename__ for cls in ALL_CCW_CLASSES]
assert len(names) == len(set(names))
# ── Field type correctness ───────────────────────────────────────
class TestFieldTypes:
"""CCW tables use str, float, and date field types."""
def test_field_types_are_expected(self) -> None:
allowed = {str, float, date}
for cls in ALL_CCW_CLASSES:
for field_name, field_info in cls.model_fields.items():
annotation = field_info.annotation
# Annotation is `T | None` — extract the base type
# For union types, __args__ gives (T, NoneType)
if hasattr(annotation, "__args__"):
base_types = {t for t in annotation.__args__ if t is not type(None)}
assert base_types.issubset(allowed), (
f"{cls.__name__}.{field_name}: {base_types} not in {allowed}"
)
# ── Construction ─────────────────────────────────────────────────
class TestConstruction:
def test_empty_construction(self) -> None:
obj = ip.IpBase()
assert obj.bene_id is None
assert obj.clm_id is None
def test_construction_with_kwargs(self) -> None:
obj = carrier.CarrierBase(
bene_id="BEN123",
clm_id="CLM456",
clm_pmt_amt=1234.56,
)
assert obj.bene_id == "BEN123"
assert obj.clm_pmt_amt == 1234.56
def test_date_field(self) -> None:
obj = carrier.CarrierBase(clm_from_dt=date(2024, 3, 15))
assert obj.clm_from_dt == date(2024, 3, 15)
def test_from_attributes_config(self) -> None:
assert ip.IpBase.model_config.get("from_attributes") is True
# ── Spot checks — largest tables ─────────────────────────────────
class TestSpotChecks:
def test_ip_base_is_largest(self) -> None:
assert len(ip.IpBase.column_names()) == 252
def test_snf_base_field_count(self) -> None:
assert len(snf.SnfBase.column_names()) == 180
def test_hop_base_field_count(self) -> None:
assert len(hop.HopBase.column_names()) == 167
def test_carrier_line_field_count(self) -> None:
assert len(carrier.CarrierLine.column_names()) == 89
def test_common_key_fields(self) -> None:
"""All Base tables should have bene_id and clm_id."""
for cls in ALL_CCW_CLASSES:
if cls.__name__.endswith("Base"):
cols = cls.column_names()
assert "bene_id" in cols, f"{cls.__name__} missing bene_id"
assert "clm_id" in cols, f"{cls.__name__} missing clm_id"
def test_demo_tables_have_demo_fields(self) -> None:
for cls in ALL_CCW_CLASSES:
if cls.__name__.endswith("Demo"):
cols = cls.column_names()
assert "demo_id_num" in cols, f"{cls.__name__} missing demo_id_num"

144
tests/cms/test_log.py Normal file
View File

@@ -0,0 +1,144 @@
"""Tests for cms.log — JSONL structured logging."""
from __future__ import annotations
import json
import logging
import pytest
from cms.log import JsonlHandler, setup
@pytest.fixture()
def log_path(tmp_path):
return tmp_path / "test.jsonl"
class TestJsonlHandler:
def test_creates_parent_dirs(self, tmp_path) -> None:
path = tmp_path / "nested" / "dir" / "log.jsonl"
handler = JsonlHandler(path)
assert path.parent.exists()
handler.close()
def test_writes_json_line(self, log_path) -> None:
handler = JsonlHandler(log_path)
logger = logging.getLogger("test.jsonl")
logger.addHandler(handler)
logger.setLevel(logging.DEBUG)
logger.info("hello world")
handler.close()
lines = log_path.read_text().strip().split("\n")
assert len(lines) == 1
entry = json.loads(lines[0])
assert entry["message"] == "hello world"
assert entry["level"] == "INFO"
assert entry["logger"] == "test.jsonl"
assert "ts" in entry
logger.removeHandler(handler)
def test_multiple_records(self, log_path) -> None:
handler = JsonlHandler(log_path)
logger = logging.getLogger("test.multi")
logger.addHandler(handler)
logger.setLevel(logging.DEBUG)
logger.info("first")
logger.warning("second")
logger.debug("third")
handler.close()
lines = log_path.read_text().strip().split("\n")
assert len(lines) == 3
levels = [json.loads(l)["level"] for l in lines]
assert levels == ["INFO", "WARNING", "DEBUG"]
logger.removeHandler(handler)
def test_custom_attrs(self, log_path) -> None:
handler = JsonlHandler(log_path)
logger = logging.getLogger("test.custom")
logger.addHandler(handler)
logger.setLevel(logging.DEBUG)
logger.info("with extra", extra={"job_id": "abc123", "count": 42})
handler.close()
entry = json.loads(log_path.read_text().strip())
assert entry["job_id"] == "abc123"
assert entry["count"] == 42
logger.removeHandler(handler)
def test_exception_info(self, log_path) -> None:
handler = JsonlHandler(log_path)
logger = logging.getLogger("test.exc")
logger.addHandler(handler)
logger.setLevel(logging.DEBUG)
try:
raise ValueError("test error")
except ValueError:
logger.exception("caught error")
handler.close()
entry = json.loads(log_path.read_text().strip())
assert entry["message"] == "caught error"
assert "exception" in entry
assert any("ValueError" in line for line in entry["exception"])
logger.removeHandler(handler)
def test_append_mode(self, log_path) -> None:
log_path.write_text('{"existing": true}\n')
handler = JsonlHandler(log_path)
logger = logging.getLogger("test.append")
logger.addHandler(handler)
logger.setLevel(logging.DEBUG)
logger.info("appended")
handler.close()
lines = log_path.read_text().strip().split("\n")
assert len(lines) == 2
logger.removeHandler(handler)
class TestSetup:
def test_returns_logger(self, log_path) -> None:
logger = setup(log_path)
assert isinstance(logger, logging.Logger)
assert logger.name == "cms"
# Cleanup
for h in logger.handlers[:]:
if isinstance(h, JsonlHandler):
h.close()
logger.removeHandler(h)
def test_sets_level(self, log_path) -> None:
logger = setup(log_path, level=logging.WARNING)
assert logger.level <= logging.WARNING
for h in logger.handlers[:]:
if isinstance(h, JsonlHandler):
h.close()
logger.removeHandler(h)
def test_idempotent_same_path(self, log_path) -> None:
logger1 = setup(log_path)
count_before = sum(1 for h in logger1.handlers if isinstance(h, JsonlHandler))
logger2 = setup(log_path)
count_after = sum(1 for h in logger2.handlers if isinstance(h, JsonlHandler))
assert count_before == count_after
assert logger1 is logger2
for h in logger1.handlers[:]:
if isinstance(h, JsonlHandler):
h.close()
logger1.removeHandler(h)
def test_different_paths_add_handlers(self, tmp_path) -> None:
p1 = tmp_path / "a.jsonl"
p2 = tmp_path / "b.jsonl"
logger = setup(p1)
before = sum(1 for h in logger.handlers if isinstance(h, JsonlHandler))
setup(p2)
after = sum(1 for h in logger.handlers if isinstance(h, JsonlHandler))
assert after == before + 1
for h in logger.handlers[:]:
if isinstance(h, JsonlHandler):
h.close()
logger.removeHandler(h)

157
tests/cms/test_table.py Normal file
View File

@@ -0,0 +1,157 @@
"""Tests for CMS table models (SQLTable subclasses).
Validates that all 150 auto-generated Pydantic table models:
- Are importable from ``cms.table``
- Have correct schema/tablename metadata
- Expose ``qualified_name()`` and ``column_names()``
- Can be constructed with nullable fields
"""
from __future__ import annotations
import inspect
from datetime import date
import pytest
import cms.table
from aco.table.base import SQLTable
# ── __init__.py completeness ─────────────────────────────────────
class TestInit:
"""cms.table __init__.py re-exports all models."""
def test_all_list_populated(self) -> None:
assert len(cms.table.__all__) == 150
def test_all_names_resolve(self) -> None:
for name in cms.table.__all__:
cls = getattr(cms.table, name)
assert inspect.isclass(cls), f"{name} is not a class"
def test_all_are_sqltable_subclasses(self) -> None:
for name in cms.table.__all__:
cls = getattr(cms.table, name)
assert issubclass(cls, SQLTable), f"{name} not a SQLTable"
# ── Schema metadata ──────────────────────────────────────────────
class TestSchemaMetadata:
"""Every CMS table has __schema__='cms' and a non-empty __tablename__."""
@pytest.fixture(params=cms.table.__all__)
def table_cls(self, request):
return getattr(cms.table, request.param)
def test_schema_is_cms(self, table_cls) -> None:
assert table_cls.__schema__ == "cms"
def test_tablename_set(self, table_cls) -> None:
assert table_cls.__tablename__, f"{table_cls.__name__} has empty tablename"
def test_qualified_name(self, table_cls) -> None:
qn = table_cls.qualified_name()
assert qn == f"cms.{table_cls.__tablename__}"
def test_column_names_non_empty(self, table_cls) -> None:
cols = table_cls.column_names()
assert len(cols) > 0, f"{table_cls.__name__} has no columns"
# ── Tablename uniqueness ─────────────────────────────────────────
class TestUniqueness:
def test_no_duplicate_tablenames(self) -> None:
names = [getattr(cms.table, n).__tablename__ for n in cms.table.__all__]
assert len(names) == len(set(names))
def test_no_duplicate_class_names(self) -> None:
assert len(cms.table.__all__) == len(set(cms.table.__all__))
# ── Field types ──────────────────────────────────────────────────
class TestFieldTypes:
"""All fields should be nullable (Optional)."""
def test_all_fields_have_defaults(self) -> None:
"""Every field should have a default of None."""
for name in cms.table.__all__:
cls = getattr(cms.table, name)
for field_name, field_info in cls.model_fields.items():
assert field_info.default is None, (
f"{cls.__name__}.{field_name} has no None default"
)
# ── Construction ─────────────────────────────────────────────────
class TestConstruction:
"""Models can be constructed empty or with kwargs."""
def test_empty_construction(self) -> None:
cls = cms.table.AccountableCareOrganizations
obj = cls()
assert obj.aco_id is None
assert obj.aco_name is None
def test_construction_with_kwargs(self) -> None:
obj = cms.table.AccountableCareOrganizations(
aco_id="A1234",
aco_name="Test ACO",
)
assert obj.aco_id == "A1234"
assert obj.aco_name == "Test ACO"
def test_date_field_construction(self) -> None:
obj = cms.table.AccountableCareOrganizations(
current_start_date=date(2024, 1, 1),
)
assert obj.current_start_date == date(2024, 1, 1)
def test_from_attributes_config(self) -> None:
cls = cms.table.AccountableCareOrganizations
assert cls.model_config.get("from_attributes") is True
def test_large_model_construction(self) -> None:
"""The largest table (AcoReachFinancialQualityResults, 131 fields)."""
cls = cms.table.AcoReachFinancialQualityResults
obj = cls()
assert len(cls.column_names()) == 131
for col in cls.column_names():
assert getattr(obj, col) is None
# ── Representative spot-checks ───────────────────────────────────
class TestSpotChecks:
"""Verify specific tables have expected columns."""
def test_medicare_monthly_enrollment(self) -> None:
cls = cms.table.MedicareMonthlyEnrollment
cols = cls.column_names()
assert "tot_benes" in cols
assert "bene_state_abrvtn" in cols
assert len(cols) == 60
def test_hospital_service_area(self) -> None:
cls = cms.table.HospitalServiceArea
assert cls.__tablename__ == "hospital_service_area"
assert len(cls.column_names()) > 0
def test_opt_out_affidavits(self) -> None:
cls = cms.table.OptOutAffidavits
assert cls.qualified_name() == "cms.opt_out_affidavits"
def test_medicaid_spending_by_drug(self) -> None:
cls = cms.table.MedicaidSpendingByDrug
assert cls.__schema__ == "cms"
assert "drug_name" in cls.column_names() or len(cls.column_names()) > 0