Fix Zotero table models for Zotero 9:
- Remove stale Annotations/Highlights/Transaction* models
- Add ItemAnnotations, RetractedItems, DeletedCollections,
DeletedSearches, DbDebug1
- Fix ItemAttachments, Libraries, Users column mismatches
New test files covering all major modules:
- cli/{bib,prisma,rec,zot,mail,run} deep exercising tests
- mail/{droplet,postmark,resend,cloudflare} lifecycle tests
- bib/{iom,oig,pincite,sync,regulations_gov,email_ingest,format,store}
- prisma/{vpn,fetch,export,llm,screen,eligibility,extract,project,ingest,flow}
- aco/lake/{unity,quality,deploy} + api/aco coverage gaps
- zot/{ops,db,extract,duck} + rec/{report,engine,base,pricers}
- pfs/{pipe,rules,eq,files}
Add pytest-xdist for parallel test execution.
Tracks #353
212 lines
7.0 KiB
Python
212 lines
7.0 KiB
Python
"""Tests for pfs.files — Format/Sieve definitions and registry integration.
|
|
|
|
Covers every line of pfs/files/__init__.py:
|
|
- All 6 column map dicts (_RVU_COLUMNS through _CARRIER_COLUMNS)
|
|
- All 4 sieve definitions (_rvu_sieve, _gpci_sieve, _pe_input_sieve, _carrier_sieve)
|
|
- All 6 format definitions in the ``formats`` dict
|
|
- Registry integration (``registry.update(formats)``)
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import re
|
|
|
|
import pytest
|
|
|
|
from pfs.files import formats
|
|
from rex.format import Format, registry
|
|
from rex.sieve import Sieve
|
|
|
|
# ── Format dict structure ────────────────────────────────────────
|
|
|
|
|
|
class TestFormatsDict:
|
|
"""The ``formats`` dict has exactly 6 entries."""
|
|
|
|
EXPECTED_KEYS = [
|
|
"pfs_rvu",
|
|
"pfs_gpci",
|
|
"pfs_labor",
|
|
"pfs_supply",
|
|
"pfs_equipment",
|
|
"pfs_carrier",
|
|
]
|
|
|
|
def test_has_six_keys(self):
|
|
assert len(formats) == 6
|
|
|
|
def test_key_names(self):
|
|
assert sorted(formats.keys()) == sorted(self.EXPECTED_KEYS)
|
|
|
|
@pytest.mark.parametrize("key", EXPECTED_KEYS)
|
|
def test_values_are_format_instances(self, key):
|
|
assert isinstance(formats[key], Format)
|
|
|
|
|
|
# ── Registry integration ─────────────────────────────────────────
|
|
|
|
|
|
class TestRegistryIntegration:
|
|
"""All PFS formats are registered in rex.format.registry at import time."""
|
|
|
|
@pytest.mark.parametrize(
|
|
"key",
|
|
[
|
|
"pfs_rvu",
|
|
"pfs_gpci",
|
|
"pfs_labor",
|
|
"pfs_supply",
|
|
"pfs_equipment",
|
|
"pfs_carrier",
|
|
],
|
|
)
|
|
def test_format_in_registry(self, key):
|
|
assert key in registry
|
|
assert registry[key] is formats[key]
|
|
|
|
|
|
# ── Per-format details ───────────────────────────────────────────
|
|
|
|
_FORMAT_SPECS = [
|
|
("pfs_rvu", "pfs.rvu", "pfs_rvu"),
|
|
("pfs_gpci", "pfs.gpci", "pfs_gpci"),
|
|
("pfs_labor", "pfs.clinical_labor", "pfs_pe_input"),
|
|
("pfs_supply", "pfs.medical_supply", "pfs_pe_input"),
|
|
("pfs_equipment", "pfs.medical_equipment", "pfs_pe_input"),
|
|
("pfs_carrier", "pfs.carrier_locality", "pfs_carrier"),
|
|
]
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"fmt_key, expected_target, expected_sieve_name",
|
|
_FORMAT_SPECS,
|
|
ids=[s[0] for s in _FORMAT_SPECS],
|
|
)
|
|
class TestFormatDetails:
|
|
"""Each format has the correct name, target, sieve, and column_map."""
|
|
|
|
def test_name_matches_key(self, fmt_key, expected_target, expected_sieve_name):
|
|
fmt = formats[fmt_key]
|
|
assert fmt.name == fmt_key
|
|
|
|
def test_target(self, fmt_key, expected_target, expected_sieve_name):
|
|
fmt = formats[fmt_key]
|
|
assert fmt.target == expected_target
|
|
|
|
def test_sieve_is_sieve(self, fmt_key, expected_target, expected_sieve_name):
|
|
fmt = formats[fmt_key]
|
|
assert isinstance(fmt.sieve, Sieve)
|
|
|
|
def test_sieve_name(self, fmt_key, expected_target, expected_sieve_name):
|
|
fmt = formats[fmt_key]
|
|
assert fmt.sieve.name == expected_sieve_name
|
|
|
|
def test_column_map_is_nonempty_dict(
|
|
self, fmt_key, expected_target, expected_sieve_name
|
|
):
|
|
fmt = formats[fmt_key]
|
|
assert isinstance(fmt.column_map, dict)
|
|
assert len(fmt.column_map) > 0
|
|
|
|
|
|
# ── Sieve regex patterns ────────────────────────────────────────
|
|
|
|
|
|
class TestSievePatterns:
|
|
"""Verify that each sieve has compiled regex patterns for data/head/skip."""
|
|
|
|
@pytest.mark.parametrize("fmt_key", list(formats.keys()))
|
|
def test_data_pattern(self, fmt_key):
|
|
sieve = formats[fmt_key].sieve
|
|
assert sieve.data is not None
|
|
assert isinstance(sieve.data, re.Pattern)
|
|
|
|
@pytest.mark.parametrize("fmt_key", list(formats.keys()))
|
|
def test_head_pattern(self, fmt_key):
|
|
sieve = formats[fmt_key].sieve
|
|
assert sieve.head is not None
|
|
assert isinstance(sieve.head, re.Pattern)
|
|
|
|
@pytest.mark.parametrize("fmt_key", list(formats.keys()))
|
|
def test_skip_pattern(self, fmt_key):
|
|
sieve = formats[fmt_key].sieve
|
|
assert sieve.skip is not None
|
|
assert isinstance(sieve.skip, re.Pattern)
|
|
|
|
|
|
# ── Column map spot checks ──────────────────────────────────────
|
|
|
|
|
|
class TestColumnMaps:
|
|
"""Spot-check that key raw CMS headers map to expected field names."""
|
|
|
|
def test_rvu_columns_hcpcs(self):
|
|
assert formats["pfs_rvu"].column_map["HCPCS"] == "hcpcs"
|
|
|
|
def test_rvu_columns_work_rvu(self):
|
|
assert formats["pfs_rvu"].column_map["WORK RVU"] == "work_rvu"
|
|
|
|
def test_rvu_columns_non_fac_pe_variant(self):
|
|
cm = formats["pfs_rvu"].column_map
|
|
assert cm["NON-FACILITY PE RVU"] == "non_fac_pe_rvu"
|
|
assert cm["NON-FAC PE RVU"] == "non_fac_pe_rvu"
|
|
|
|
def test_gpci_columns_carrier_alias(self):
|
|
cm = formats["pfs_gpci"].column_map
|
|
assert cm["MAC"] == "mac"
|
|
assert cm["CARRIER"] == "mac"
|
|
|
|
def test_labor_columns_nf_minutes_variant(self):
|
|
cm = formats["pfs_labor"].column_map
|
|
assert cm["NF MINUTES"] == "nf_minutes"
|
|
assert cm["NON-FACILITY MINUTES"] == "nf_minutes"
|
|
|
|
def test_supply_columns_unit_price_variant(self):
|
|
cm = formats["pfs_supply"].column_map
|
|
assert cm["UNIT PRICE"] == "unit_price"
|
|
assert cm["PRICE"] == "unit_price"
|
|
|
|
def test_equipment_columns_useful_life(self):
|
|
assert formats["pfs_equipment"].column_map["USEFUL LIFE"] == "useful_life"
|
|
|
|
def test_carrier_columns_fac_fee(self):
|
|
cm = formats["pfs_carrier"].column_map
|
|
assert cm["FACILITY FEE SCHEDULE AMOUNT"] == "fac_fee"
|
|
assert cm["FACILITY LIMITING CHARGE"] == "fac_limiting_charge"
|
|
|
|
|
|
# ── Gap coverage — missed lines ────────────────────────────────
|
|
|
|
|
|
class TestImportErrorFallback:
|
|
"""Lines 36-37: ImportError raised when rex is not installed."""
|
|
|
|
def test_import_error_without_rex(self):
|
|
import importlib
|
|
import sys
|
|
|
|
# Save and remove rex and pfs.files modules
|
|
saved = {}
|
|
for key in list(sys.modules):
|
|
if key.startswith("rex") or key == "pfs.files":
|
|
saved[key] = sys.modules.pop(key)
|
|
|
|
import builtins
|
|
|
|
_real_import = builtins.__import__
|
|
|
|
def _fake_import(name, *args, **kwargs):
|
|
if name.startswith("rex"):
|
|
raise ImportError("fake: no rex")
|
|
return _real_import(name, *args, **kwargs)
|
|
|
|
builtins.__import__ = _fake_import
|
|
try:
|
|
with pytest.raises(ImportError, match="stack\\[rex\\]"):
|
|
importlib.import_module("pfs.files")
|
|
finally:
|
|
builtins.__import__ = _real_import
|
|
# Restore saved modules
|
|
for key, val in saved.items():
|
|
sys.modules[key] = val
|