feat: add import templates
This commit is contained in:
84
tests/test_import_templates.py
Normal file
84
tests/test_import_templates.py
Normal file
@@ -0,0 +1,84 @@
|
||||
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()
|
||||
Reference in New Issue
Block a user