fin-hub/tests/test_coupling.py

79 lines
2.4 KiB
Python

import pytest
from fin_hub.coupling.ops_hub import ServiceCostLine, build_service_cost_report
from fin_hub.ingest.hosteurope import parse_hosteurope_csv
from pathlib import Path
def test_build_service_cost_report_groups_by_service():
rows = parse_hosteurope_csv(Path(__file__).parent / "fixtures" / "hosteurope.csv")
lines = [
ServiceCostLine(
service_id=row.service_id,
environment=row.environment,
period_month=row.period_month,
amount=row.amount,
currency=row.currency,
source=row.source,
)
for row in rows
]
report = build_service_cost_report(lines)
assert report["signal"] == "service_cost_attribution"
assert len(report["services"]) == 2
assert report["totals_by_month"]["2026-06"] == pytest.approx(99.8)
assert report["attributions"][0]["cost_attribution_key"] is None
def test_build_service_cost_report_groups_by_client_attribution():
lines = [
ServiceCostLine(
service_id="cluster",
environment="production",
period_month="2026-07",
amount=42.0,
currency="EUR",
source="fixture",
client_id="acme",
application_id="portal",
app_instance_id="prod-01",
cost_attribution_key="client:acme|app:portal|instance:prod-01",
)
]
report = build_service_cost_report(lines)
assert report["attributions"] == [
{
"cost_attribution_key": "client:acme|app:portal|instance:prod-01",
"client_id": "acme",
"application_id": "portal",
"app_instance_id": "prod-01",
"currency": "EUR",
"months": {"2026-07": 42.0},
"total": 42.0,
}
]
def test_client_attribution_totals_do_not_mix_currencies():
common = {
"service_id": "cluster",
"environment": "production",
"period_month": "2026-07",
"source": "fixture",
"client_id": "acme",
"application_id": "portal",
"app_instance_id": "prod-01",
}
report = build_service_cost_report(
[
ServiceCostLine(amount=42.0, currency="EUR", **common),
ServiceCostLine(amount=50.0, currency="USD", **common),
]
)
assert {(row["currency"], row["total"]) for row in report["attributions"]} == {
("EUR", 42.0),
("USD", 50.0),
}