"""Invariants of the cleaned panel (run after `make clean`).""" import json, pandas as pd, pytest from src.common import ROOT, P, REGIONS @pytest.fixture(scope="module") def li(): return pd.read_parquet(P["interim"] / "listings_clean.parquet") @pytest.fixture(scope="module") def sm(): return pd.read_parquet(P["interim"] / "stores_master.parquet") def test_flow_monotone(): flow = json.load(open(ROOT / "experiments" / "sample_flow.json"))["flow"] vals = [v for _, v in flow] assert all(a >= b for a, b in zip(vals, vals[1:])) def test_price_sample_subset(li): assert not (li.f_analysis_price & ~li.f_analysis_assort).any() s = li[li.f_analysis_price] assert (s.price > 0).all() and (s.price <= 50_000).all() and (s.currency == "CAD").all() def test_one_rep_per_store_title(li): a = li[li.f_analysis_assort] assert not a.duplicated(["store_id", "title_norm"]).any() def test_no_sibling_nonrep_in_assortment(li): assert not li.loc[li.f_analysis_assort, "f_sibling_dup"].any() def test_regions_canonical(sm): assert set(sm.region_final.unique()) <= set(REGIONS) | {"Inconnue"} assert sm.id.is_unique def test_store_listing_counts_consistent(li, sm): a = li[li.f_analysis_assort].groupby("store_id").size() m = sm.set_index("id").n_listings assert (a.reindex(m.index).fillna(0).astype(int) == m).all() def test_match_pairs_cross_store(): pr = pd.read_parquet(P["interim"] / "match_pairs.parquet") assert (pr.store_a != pr.store_b).all() and pr.tier.isin(list("ABCD")).all() sib = pd.read_parquet(P["interim"] / "sibling_stores.parquet") rep = sib.set_index("id").sibling_rep assert not (pr.store_a.map(rep).fillna(pr.store_a) == pr.store_b.map(rep).fillna(pr.store_b)).any()