107 lines
3.3 KiB
Python
107 lines
3.3 KiB
Python
"""Regression tests for the recon package — type round-trips, join_path,
|
|
and column_to_tables index."""
|
|
|
|
from api.recon.types import Recon, Relationship, Table, Column, Metric
|
|
|
|
|
|
def _sample_recon() -> Recon:
|
|
cols_account = [
|
|
Column("account_id", "BIGINT", False),
|
|
Column("district_id", "BIGINT", True),
|
|
]
|
|
cols_district = [
|
|
Column("district_id", "BIGINT", False),
|
|
Column("A2", "TEXT", True),
|
|
Column("A11", "BIGINT", True),
|
|
]
|
|
cols_loan = [
|
|
Column("loan_id", "BIGINT", False),
|
|
Column("account_id", "BIGINT", True),
|
|
Column("amount", "BIGINT", True),
|
|
Column("status", "TEXT", True),
|
|
]
|
|
rels = [
|
|
Relationship("account", "district_id", "district", "district_id"),
|
|
Relationship("loan", "account_id", "account", "account_id"),
|
|
]
|
|
c2t = {
|
|
"account_id": sorted(["account", "loan"]),
|
|
"district_id": sorted(["account", "district"]),
|
|
"A2": ["district"],
|
|
"A11": ["district"],
|
|
"loan_id": ["loan"],
|
|
"amount": ["loan"],
|
|
"status": ["loan"],
|
|
}
|
|
return Recon(
|
|
schema="financial",
|
|
tables={
|
|
"account": Table("account", "Accounts", cols_account),
|
|
"district": Table("district", "Districts", cols_district),
|
|
"loan": Table("loan", "Loans", cols_loan),
|
|
},
|
|
metrics={
|
|
"loan_volume": Metric("loan_volume", "Total CZK lent",
|
|
"SUM(amount)", "loan", None, "CZK"),
|
|
},
|
|
column_to_tables=c2t,
|
|
relationships=rels,
|
|
)
|
|
|
|
|
|
def test_owning_tables():
|
|
r = _sample_recon()
|
|
assert r.owning_tables("A2") == ["district"]
|
|
assert r.owning_tables("amount") == ["loan"]
|
|
assert r.owning_tables("account_id") == ["account", "loan"]
|
|
assert r.owning_tables("nonsense") == []
|
|
|
|
|
|
def test_join_path_direct():
|
|
r = _sample_recon()
|
|
assert r.join_path("loan", "account") == ["loan", "account"]
|
|
assert r.join_path("account", "district") == ["account", "district"]
|
|
|
|
|
|
def test_join_path_multi_hop():
|
|
r = _sample_recon()
|
|
assert r.join_path("loan", "district") == ["loan", "account", "district"]
|
|
|
|
|
|
def test_join_path_same():
|
|
r = _sample_recon()
|
|
assert r.join_path("loan", "loan") == ["loan"]
|
|
|
|
|
|
def test_join_path_unknown_returns_none():
|
|
r = _sample_recon()
|
|
assert r.join_path("loan", "does_not_exist") is None
|
|
|
|
|
|
def test_recon_to_dict_from_dict_roundtrip():
|
|
r = _sample_recon()
|
|
d = r.to_dict()
|
|
r2 = Recon.from_dict(d)
|
|
assert r2.schema == r.schema
|
|
assert sorted(r2.tables) == sorted(r.tables)
|
|
assert sorted(r2.metrics) == sorted(r.metrics)
|
|
assert r2.column_to_tables == r.column_to_tables
|
|
assert len(r2.relationships) == len(r.relationships)
|
|
assert r2.join_path("loan", "district") == ["loan", "account", "district"]
|
|
|
|
|
|
def test_relationship_parse_dotted():
|
|
r = Relationship.parse({"from": "loan.account_id", "to": "account.account_id"})
|
|
assert r.from_table == "loan"
|
|
assert r.from_column == "account_id"
|
|
assert r.to_table == "account"
|
|
assert r.to_column == "account_id"
|
|
|
|
|
|
def test_relationship_parse_explicit():
|
|
r = Relationship.parse({
|
|
"from_table": "loan", "from_column": "account_id",
|
|
"to_table": "account", "to_column": "account_id",
|
|
})
|
|
assert r.from_table == "loan"
|