generated from coulomb/repo-seed
Implement comparable LTV engine and close WP-0005
This commit is contained in:
69
projects/coulomb-pricing/tests/test_comparable_ltv.py
Normal file
69
projects/coulomb-pricing/tests/test_comparable_ltv.py
Normal file
@@ -0,0 +1,69 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
from observatory.economics import build_snapshot
|
||||
from observatory.load import (
|
||||
load_ltv_scenarios,
|
||||
load_membership,
|
||||
load_monthly_ledger,
|
||||
load_payment_records,
|
||||
load_pricing_models,
|
||||
load_product,
|
||||
)
|
||||
from observatory.simulator import build_pricing_simulations
|
||||
from observatory.usage import load_usage_records
|
||||
|
||||
DATA_DIR = Path(__file__).resolve().parent.parent / "data"
|
||||
|
||||
|
||||
def _snapshot(period: str = "2026-06"):
|
||||
product = load_product(DATA_DIR)
|
||||
models = load_pricing_models(DATA_DIR)
|
||||
members = load_membership(DATA_DIR)
|
||||
payments = load_payment_records(DATA_DIR)
|
||||
ledger = load_monthly_ledger(DATA_DIR)
|
||||
return build_snapshot(period, product, models, members, payments, ledger)
|
||||
|
||||
|
||||
def test_simulations_include_reference_model_and_profile_comparisons() -> None:
|
||||
snapshot = _snapshot()
|
||||
models = load_pricing_models(DATA_DIR)
|
||||
simulations = build_pricing_simulations(
|
||||
snapshot,
|
||||
models,
|
||||
snapshot.cost_per_member,
|
||||
usage_records=load_usage_records(DATA_DIR),
|
||||
scenario_catalog=load_ltv_scenarios(DATA_DIR),
|
||||
)
|
||||
|
||||
assert simulations["primary_profile_id"] == "solo-builder"
|
||||
assert simulations["reference_model_id"] is not None
|
||||
assert simulations["best_ltv_scenario_id"] is not None
|
||||
assert len(simulations["profile_comparisons"]) == 2
|
||||
assert simulations["scenarios"][0]["average_comparable_customer_lifetime_value"] is not None
|
||||
assert simulations["scenarios"][0]["sensitivity"]
|
||||
|
||||
|
||||
def test_small_team_profile_has_reference_and_non_passing_candidates() -> None:
|
||||
snapshot = _snapshot()
|
||||
models = load_pricing_models(DATA_DIR)
|
||||
simulations = build_pricing_simulations(
|
||||
snapshot,
|
||||
models,
|
||||
snapshot.cost_per_member,
|
||||
usage_records=load_usage_records(DATA_DIR),
|
||||
scenario_catalog=load_ltv_scenarios(DATA_DIR),
|
||||
)
|
||||
|
||||
small_team = next(
|
||||
item for item in simulations["profile_comparisons"] if item["profile"]["id"] == "small-team"
|
||||
)
|
||||
|
||||
assert small_team["reference_model_id"] is not None
|
||||
assert small_team["best_valid_model_id"] is not None
|
||||
assert any(
|
||||
not comparison["passes_required_improvement"]
|
||||
for comparison in small_team["comparisons"]
|
||||
if comparison["model_id"] != small_team["reference_model_id"]
|
||||
)
|
||||
Reference in New Issue
Block a user