From ccdc3572c802a29f54ceb85d020bb9ab8ffe040c Mon Sep 17 00:00:00 2001 From: Tyler Hoang Date: Mon, 29 Jun 2026 01:37:18 -0700 Subject: test: add DCF and valuation backend tests --- backend/tests/test_dcf_advanced.py | 148 +++++++++++++++++++++++++++++++++++++ 1 file changed, 148 insertions(+) create mode 100644 backend/tests/test_dcf_advanced.py (limited to 'backend/tests/test_dcf_advanced.py') diff --git a/backend/tests/test_dcf_advanced.py b/backend/tests/test_dcf_advanced.py new file mode 100644 index 0000000..20f6921 --- /dev/null +++ b/backend/tests/test_dcf_advanced.py @@ -0,0 +1,148 @@ +import pytest + +from app.services.data_service import _run_dcf_explicit_build + + +_APPROX = pytest.approx + + +def test_run_dcf_explicit_build_two_year_reference_scenario() -> None: + # Given + base_revenue = 1_000.0 + + # When + result = _run_dcf_explicit_build( + base_revenue=base_revenue, + revenue_growth=[0.10, 0.05], + ebitda_margin=[0.30, 0.32], + dna_pct_revenue=[0.05, 0.05], + capex_pct_revenue=[0.07, 0.07], + nwc_chg_pct_delta_rev=[0.02, 0.02], + tax_rate=[0.25, 0.25], + wacc=0.10, + terminal_growth=0.03, + shares_outstanding=100.0, + total_debt=50.0, + cash=10.0, + preferred_equity=5.0, + minority_interest=3.0, + projection_years=2, + ) + + # Then + assert result["available"] is True + assert result["base_fcf"] == _APPROX(184.25) + assert result["fcf_pv_sum"] == _APPROX(357.42928814344134) + assert result["terminal_value_pv"] == _APPROX(2_674.37743224556) + assert result["enterprise_value"] == _APPROX(3_031.8067203890014) + assert result["net_debt"] == 40.0 + assert result["equity_value"] == _APPROX(2_983.8067203890014) + assert result["intrinsic_value_per_share"] == _APPROX(29.838067203890013) + assert result["wacc"] == 0.10 + assert result["terminal_growth"] == 0.03 + assert result["projection_years"] == 2 + + +def test_run_dcf_explicit_build_terminal_growth_at_wacc_returns_error() -> None: + # Given / When + result = _run_dcf_explicit_build( + base_revenue=1_000.0, + revenue_growth=[0.05], + ebitda_margin=[0.30], + dna_pct_revenue=[0.05], + capex_pct_revenue=[0.07], + nwc_chg_pct_delta_rev=[0.02], + tax_rate=[0.25], + wacc=0.10, + terminal_growth=0.10, + shares_outstanding=100.0, + total_debt=0.0, + cash=0.0, + preferred_equity=0.0, + minority_interest=0.0, + projection_years=1, + ) + + # Then + assert result["available"] is True + assert "Terminal growth" in result["error"] + assert "intrinsic_value_per_share" not in result + + +def test_run_dcf_explicit_build_zero_wacc_returns_error() -> None: + # Given / When + result = _run_dcf_explicit_build( + base_revenue=1_000.0, + revenue_growth=[0.05], + ebitda_margin=[0.30], + dna_pct_revenue=[0.05], + capex_pct_revenue=[0.07], + nwc_chg_pct_delta_rev=[0.02], + tax_rate=[0.25], + wacc=0.0, + terminal_growth=0.03, + shares_outstanding=100.0, + total_debt=0.0, + cash=0.0, + preferred_equity=0.0, + minority_interest=0.0, + projection_years=1, + ) + + # Then + assert result["available"] is True + assert "WACC" in result["error"] + assert "intrinsic_value_per_share" not in result + + +@pytest.mark.parametrize("shares_outstanding", [0.0, -1.0]) +def test_run_dcf_explicit_build_nonpositive_shares_return_error(shares_outstanding: float) -> None: + # Given / When + result = _run_dcf_explicit_build( + base_revenue=1_000.0, + revenue_growth=[0.05], + ebitda_margin=[0.30], + dna_pct_revenue=[0.05], + capex_pct_revenue=[0.07], + nwc_chg_pct_delta_rev=[0.02], + tax_rate=[0.25], + wacc=0.10, + terminal_growth=0.03, + shares_outstanding=shares_outstanding, + total_debt=0.0, + cash=0.0, + preferred_equity=0.0, + minority_interest=0.0, + projection_years=1, + ) + + # Then + assert result["available"] is True + assert "Shares outstanding" in result["error"] + assert "intrinsic_value_per_share" not in result + + +def test_run_dcf_explicit_build_zero_base_revenue_returns_error() -> None: + # Given / When + result = _run_dcf_explicit_build( + base_revenue=0.0, + revenue_growth=[0.05], + ebitda_margin=[0.30], + dna_pct_revenue=[0.05], + capex_pct_revenue=[0.07], + nwc_chg_pct_delta_rev=[0.02], + tax_rate=[0.25], + wacc=0.10, + terminal_growth=0.03, + shares_outstanding=100.0, + total_debt=0.0, + cash=0.0, + preferred_equity=0.0, + minority_interest=0.0, + projection_years=1, + ) + + # Then + assert result["available"] is True + assert "Base revenue" in result["error"] + assert "intrinsic_value_per_share" not in result -- cgit v1.3-2-g0d8e