133 lines
4.7 KiB
Python
133 lines
4.7 KiB
Python
"""Smoke test integral — validate all 4 county PA adapters work end-to-end.
|
|
|
|
Pulls one real deal from DB per county, runs PA fetch via unified router,
|
|
verifies key fields populated. Output: pass/fail summary for user confidence.
|
|
"""
|
|
from __future__ import annotations
|
|
import sys
|
|
import time
|
|
import sqlite3
|
|
sys.path.insert(0, ".")
|
|
|
|
|
|
def test_county(county: str, expect_real_data: bool = True) -> dict:
|
|
"""Pick a deal from DB for this county, run PA fetch, validate."""
|
|
out = {"county": county, "status": "?", "errors": [], "details": {}}
|
|
|
|
# Find a testable deal
|
|
conn = sqlite3.connect("data/deals.db")
|
|
conn.row_factory = sqlite3.Row
|
|
cur = conn.cursor()
|
|
cur.execute(
|
|
"SELECT id, parcel_id, address FROM deals "
|
|
"WHERE county=? AND parcel_id IS NOT NULL AND parcel_id != '' LIMIT 1",
|
|
(county,)
|
|
)
|
|
row = cur.fetchone()
|
|
conn.close()
|
|
|
|
if not row:
|
|
out["status"] = "SKIP"
|
|
out["errors"].append(f"No deals in DB for {county}")
|
|
return out
|
|
|
|
deal_id = row["id"]
|
|
parcel = row["parcel_id"]
|
|
address = row["address"]
|
|
out["details"] = {
|
|
"deal_id": deal_id, "parcel_id": parcel, "address": address[:60] if address else "?",
|
|
}
|
|
|
|
# Run PA fetch via unified router
|
|
try:
|
|
from data_fetchers.property_appraiser import fetch_pa_record, is_pa_supported
|
|
if not is_pa_supported(county, "FL"):
|
|
out["status"] = "NOT_IMPLEMENTED"
|
|
return out
|
|
t0 = time.perf_counter()
|
|
rec = fetch_pa_record(county_name=county, state="FL",
|
|
address=address, parcel_id=parcel)
|
|
elapsed = round(time.perf_counter() - t0, 1)
|
|
out["details"]["elapsed_sec"] = elapsed
|
|
|
|
if not rec:
|
|
out["status"] = "FAIL"
|
|
out["errors"].append("PA router returned None")
|
|
return out
|
|
|
|
if rec.get("errors"):
|
|
out["status"] = "FAIL"
|
|
out["errors"].extend(rec["errors"][:2])
|
|
|
|
# Validate key fields
|
|
required = ["owner_name", "year_built", "just_value_current"]
|
|
missing = [f for f in required if not rec.get(f)]
|
|
if missing and expect_real_data:
|
|
out["status"] = "PARTIAL"
|
|
out["errors"].append(f"Missing fields: {missing}")
|
|
elif not missing:
|
|
out["status"] = "OK"
|
|
|
|
# Capture the good stuff
|
|
out["details"].update({
|
|
"owner": rec.get("owner_name"),
|
|
"year_built": rec.get("year_built"),
|
|
"just_value": rec.get("just_value_current"),
|
|
"assessed_value": rec.get("assessed_value_current"),
|
|
"homestead": rec.get("homestead_active"),
|
|
"sales_count": len(rec.get("sales_history") or []),
|
|
"renovation_signal": (rec.get("renovation_signal") or {}).get("is_flip_in_progress", False),
|
|
})
|
|
except Exception as e:
|
|
import traceback
|
|
out["status"] = "ERROR"
|
|
out["errors"].append(f"{type(e).__name__}: {e}")
|
|
out["details"]["trace"] = traceback.format_exc()[:300]
|
|
|
|
return out
|
|
|
|
|
|
def main():
|
|
counties = ["Duval", "Broward", "Miami-Dade", "Palm Beach"]
|
|
results = []
|
|
print("=" * 75)
|
|
print("PA Adapters Smoke Test — 4 counties")
|
|
print("=" * 75)
|
|
|
|
for c in counties:
|
|
print(f"\nTesting {c}...")
|
|
result = test_county(c)
|
|
results.append(result)
|
|
status = result["status"]
|
|
icon = {"OK": "PASS", "PARTIAL": "PART", "SKIP": "SKIP",
|
|
"FAIL": "FAIL", "ERROR": "ERR ", "NOT_IMPLEMENTED": "NOIM"}.get(status, "??")
|
|
det = result["details"]
|
|
print(f" [{icon}] {c} (deal id={det.get('deal_id','?')})")
|
|
if status in ("OK", "PARTIAL"):
|
|
print(f" Address: {det.get('address')}")
|
|
print(f" Owner: {det.get('owner')!r}")
|
|
print(f" Built: {det.get('year_built')}")
|
|
print(f" Just $: {det.get('just_value')}")
|
|
print(f" Assessed: {det.get('assessed_value')}")
|
|
print(f" Homestead:{det.get('homestead')}")
|
|
print(f" Sales: {det.get('sales_count')} records")
|
|
print(f" Elapsed: {det.get('elapsed_sec')}s")
|
|
if result["errors"]:
|
|
for e in result["errors"][:2]:
|
|
e_safe = str(e)[:120].encode("ascii", "replace").decode("ascii")
|
|
print(f" ERROR: {e_safe}")
|
|
|
|
# Summary
|
|
print()
|
|
print("=" * 75)
|
|
pass_count = sum(1 for r in results if r["status"] == "OK")
|
|
print(f"SUMMARY: {pass_count}/{len(results)} counties PASS")
|
|
print("=" * 75)
|
|
for r in results:
|
|
icon = "PASS" if r["status"] == "OK" else r["status"]
|
|
print(f" {icon:6s} {r['county']}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|