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)
158 lines
5.6 KiB
Python
158 lines
5.6 KiB
Python
"""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
|