85 lines
3.2 KiB
Python
85 lines
3.2 KiB
Python
from __future__ import annotations
|
|
|
|
import csv
|
|
import tempfile
|
|
import unittest
|
|
from pathlib import Path
|
|
|
|
from shanghai_housing.db import connect, import_template_file
|
|
from shanghai_housing.import_templates import validate_csv_file, validate_import_rows
|
|
|
|
|
|
class ImportTemplateTests(unittest.TestCase):
|
|
def test_validates_area_monthly_metrics_template_file(self) -> None:
|
|
result = validate_csv_file(
|
|
"area_monthly_metrics",
|
|
Path("docs/import_templates/area_monthly_metrics.csv"),
|
|
)
|
|
|
|
self.assertTrue(result.valid)
|
|
self.assertEqual(result.row_count, 1)
|
|
self.assertEqual(result.errors, [])
|
|
|
|
def test_reports_missing_required_value_and_invalid_range(self) -> None:
|
|
rows = [
|
|
{
|
|
"area_id": "",
|
|
"month": "2026-13",
|
|
"transaction_count": "-1",
|
|
"transaction_price_psm": "abc",
|
|
"listing_count": "10",
|
|
"listing_price_psm": "100",
|
|
"median_days_on_market": "30",
|
|
"rent_price_psm": "3",
|
|
"new_supply_units": "0",
|
|
"land_residential_gfa_sqm": "0",
|
|
"mortgage_rate_pct": "3.35",
|
|
"policy_signal": "3",
|
|
"source": "manual",
|
|
}
|
|
]
|
|
|
|
result = validate_import_rows("area_monthly_metrics", rows)
|
|
|
|
self.assertFalse(result.valid)
|
|
messages = {(error.column, error.message) for error in result.errors}
|
|
self.assertIn(("area_id", "value is required"), messages)
|
|
self.assertIn(("month", "must be YYYY-MM"), messages)
|
|
self.assertIn(("transaction_count", "must be >= 0"), messages)
|
|
self.assertIn(("transaction_price_psm", "must be a number"), messages)
|
|
self.assertIn(("policy_signal", "must be <= 2"), messages)
|
|
|
|
def test_reports_unexpected_headers_from_csv(self) -> None:
|
|
with tempfile.TemporaryDirectory() as tmpdir:
|
|
path = Path(tmpdir) / "bad.csv"
|
|
with path.open("w", encoding="utf-8", newline="") as handle:
|
|
writer = csv.DictWriter(handle, fieldnames=["area_id", "unknown"])
|
|
writer.writeheader()
|
|
writer.writerow({"area_id": "qiantan", "unknown": "value"})
|
|
|
|
result = validate_csv_file("area_monthly_metrics", path)
|
|
|
|
self.assertFalse(result.valid)
|
|
messages = {(error.row, error.column, error.message) for error in result.errors}
|
|
self.assertIn((0, "unknown", "unexpected header"), messages)
|
|
self.assertIn((0, "month", "missing required header"), messages)
|
|
|
|
def test_imports_valid_template_file_to_sqlite(self) -> None:
|
|
with tempfile.TemporaryDirectory() as tmpdir:
|
|
db_path = Path(tmpdir) / "research.sqlite"
|
|
count = import_template_file(
|
|
db_path,
|
|
"policy_events",
|
|
Path("docs/import_templates/policy_events.csv"),
|
|
)
|
|
with connect(db_path) as conn:
|
|
rows = conn.execute("SELECT * FROM policy_events").fetchall()
|
|
|
|
self.assertEqual(count, 1)
|
|
self.assertEqual(len(rows), 1)
|
|
self.assertEqual(rows[0]["level"], "shanghai")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|