Files
stack/tests/qpp/test_rules.py

241 lines
8.4 KiB
Python

"""Tests for qpp — QP / Advanced-APM registry.
Covers src/qpp/__init__.py:
- QpThresholds / RiskStandards / QppProposed model construction
- QppYear model construction with required and default fields
- QPP dict: performance years 2023-2026, payment_year = performance_year + 2
- qp_cf_applies: False before performance year 2024, True from 2024 onward
- Every entry has a non-empty citation
- QPP[2026].proposed is CMS-1832-P
- for_payment_year(year) lookup, including KeyError on miss
- Exact-value asserts for transcribed thresholds (see task-6-report.md)
"""
from __future__ import annotations
import pytest
from qpp import QPP, QppProposed, QppYear, QpThresholds, RiskStandards, for_payment_year
# ── QpThresholds model ───────────────────────────────────────────
class TestQpThresholds:
def test_construction(self):
t = QpThresholds(payment_amount_pct=75.0, patient_count_pct=50.0)
assert t.payment_amount_pct == 75.0
assert t.patient_count_pct == 50.0
# ── RiskStandards model ──────────────────────────────────────────
class TestRiskStandards:
def test_construction(self):
r = RiskStandards(revenue_nominal_pct=8.0, benchmark_nominal_pct=3.0)
assert r.revenue_nominal_pct == 8.0
assert r.benchmark_nominal_pct == 3.0
def test_default_notes(self):
r = RiskStandards(revenue_nominal_pct=8.0, benchmark_nominal_pct=3.0)
assert r.notes == ""
def test_default_benchmark_nominal_pct(self):
r = RiskStandards(revenue_nominal_pct=8.0)
assert r.benchmark_nominal_pct is None
# ── QppProposed model ────────────────────────────────────────────
class TestQppProposed:
def test_required_fields(self):
p = QppProposed(
cms_rule_id="CMS-0000-P",
federal_register_citation="99 FR 1",
changes="proposed no change to anything",
)
assert p.cms_rule_id == "CMS-0000-P"
assert p.changes == "proposed no change to anything"
def test_default_optional_blocks(self):
p = QppProposed(
cms_rule_id="CMS-0000-P",
federal_register_citation="99 FR 1",
changes="no change",
)
assert p.qp_thresholds is None
assert p.partial_qp_thresholds is None
assert p.risk_standards is None
# ── QppYear model ─────────────────────────────────────────────────
class TestQppYear:
def _minimal_kwargs(self):
return dict(
performance_year=2099,
payment_year=2101,
qp_thresholds=QpThresholds(payment_amount_pct=75.0, patient_count_pct=50.0),
partial_qp_thresholds=QpThresholds(
payment_amount_pct=50.0, patient_count_pct=35.0
),
risk_standards=RiskStandards(
revenue_nominal_pct=8.0, benchmark_nominal_pct=3.0
),
apm_incentive_pct=None,
qp_cf_applies=True,
)
def test_required_fields(self):
y = QppYear(**self._minimal_kwargs())
assert y.performance_year == 2099
assert y.payment_year == 2101
def test_default_cehrt_required(self):
y = QppYear(**self._minimal_kwargs())
assert y.cehrt_required is True
def test_default_citation(self):
y = QppYear(**self._minimal_kwargs())
assert y.citation == ""
def test_default_proposed(self):
y = QppYear(**self._minimal_kwargs())
assert y.proposed is None
# ── QPP dict structure ───────────────────────────────────────────
class TestQppDict:
EXPECTED_YEARS = [2023, 2024, 2025, 2026]
def test_count(self):
assert len(QPP) == 4
def test_keys(self):
assert sorted(QPP.keys()) == self.EXPECTED_YEARS
@pytest.mark.parametrize("year", EXPECTED_YEARS)
def test_values_are_qppyear(self, year):
assert isinstance(QPP[year], QppYear)
@pytest.mark.parametrize("year", EXPECTED_YEARS)
def test_performance_year_field_matches_key(self, year):
assert QPP[year].performance_year == year
@pytest.mark.parametrize("year", EXPECTED_YEARS)
def test_payment_year_is_performance_year_plus_2(self, year):
assert QPP[year].payment_year == year + 2
@pytest.mark.parametrize("year", EXPECTED_YEARS)
def test_citation_non_empty(self, year):
assert QPP[year].citation != ""
class TestQpCfApplies:
"""payment year 2026 (performance year 2024) is the first split-CF year."""
def test_2023_false(self):
assert QPP[2023].qp_cf_applies is False
def test_2024_true(self):
assert QPP[2024].qp_cf_applies is True
def test_2025_true(self):
assert QPP[2025].qp_cf_applies is True
def test_2026_true(self):
assert QPP[2026].qp_cf_applies is True
class TestApmIncentivePct:
"""Lump-sum APM Incentive Payment sunsets after payment year 2026."""
def test_2023_incentive(self):
assert QPP[2023].apm_incentive_pct == 3.5
def test_2024_incentive(self):
assert QPP[2024].apm_incentive_pct == 1.88
def test_2025_no_incentive(self):
assert QPP[2025].apm_incentive_pct is None
def test_2026_no_incentive(self):
assert QPP[2026].apm_incentive_pct is None
# ── QPP[2026].proposed — CMS-1832-P ──────────────────────────────
class TestProposed:
def test_2026_has_proposed(self):
p = QPP[2026].proposed
assert p is not None
assert p.cms_rule_id == "CMS-1832-P"
assert p.federal_register_citation == "90 FR 32352"
def test_2026_changes_non_empty(self):
assert len(QPP[2026].proposed.changes) > 0
def test_earlier_years_have_no_proposed_block(self):
assert QPP[2023].proposed is None
assert QPP[2024].proposed is None
assert QPP[2025].proposed is None
# ── Exact transcribed threshold values ───────────────────────────
class TestSpecificValues:
"""Verify transcribed QP/Partial QP thresholds and risk standards.
See task-6-report.md transcription table for sourcing per value."""
@pytest.mark.parametrize("year", [2023, 2024, 2025, 2026])
def test_qp_thresholds(self, year):
assert QPP[year].qp_thresholds.payment_amount_pct == 75.0
assert QPP[year].qp_thresholds.patient_count_pct == 50.0
@pytest.mark.parametrize("year", [2023, 2024, 2025, 2026])
def test_partial_qp_thresholds(self, year):
assert QPP[year].partial_qp_thresholds.payment_amount_pct == 50.0
assert QPP[year].partial_qp_thresholds.patient_count_pct == 35.0
@pytest.mark.parametrize("year", [2023, 2024, 2025, 2026])
def test_risk_standards(self, year):
# Revenue-based standard (42 CFR 414.1415(c)(3)(i)(A)) is
# transcribed (8%); the benchmark-based standard (42 CFR
# 414.1415(c)(3)(i)(B)) is not stated as a bare number in this
# repository's FR corpus and is left None — see
# RiskStandards.notes / module docstring.
assert QPP[year].risk_standards.revenue_nominal_pct == 8.0
assert QPP[year].risk_standards.benchmark_nominal_pct is None
@pytest.mark.parametrize("year", [2023, 2024, 2025, 2026])
def test_cehrt_required(self, year):
assert QPP[year].cehrt_required is True
# ── for_payment_year lookup ──────────────────────────────────────
class TestForPaymentYear:
def test_2025_maps_to_performance_2023(self):
assert for_payment_year(2025) is QPP[2023]
def test_2026_maps_to_performance_2024(self):
assert for_payment_year(2026) is QPP[2024]
def test_2027_maps_to_performance_2025(self):
assert for_payment_year(2027) is QPP[2025]
def test_2028_maps_to_performance_2026(self):
assert for_payment_year(2028) is QPP[2026]
def test_unknown_payment_year_raises_keyerror(self):
with pytest.raises(KeyError):
for_payment_year(1999)