Skip to main content
Glama

MCP Stock Details Server

by whdghk1907
test_advanced_company_tools.pyβ€’15.9 kB
""" Unit tests for advanced company analysis tools TDD Red Phase: Write failing tests for enhanced functionality """ import pytest import asyncio from unittest.mock import Mock, AsyncMock, patch from datetime import datetime, date from typing import Dict, Any, List # Test imports will fail initially - this is expected in TDD Red phase try: from src.tools.company_tools import CompanyAnalyzer from src.models.company import CompanyOverview, FinancialData, BusinessSegment, ShareholderInfo from src.exceptions import MCPStockDetailsError, CompanyNotFoundError, InsufficientDataError from src.utils.financial_calculator import FinancialCalculator except ImportError: # Expected in Red phase - we haven't implemented these yet pass class TestCompanyAnalyzer: """Test cases for enhanced company analysis functionality""" @pytest.fixture def company_analyzer(self): """Create company analyzer instance for testing""" return CompanyAnalyzer() @pytest.fixture def sample_company_data(self): """Sample company data for testing""" return { "company_code": "005930", "company_name": "μ‚Όμ„±μ „μž", "industry_code": "26211", "industry_name": "λ°˜λ„μ²΄ μ œμ‘°μ—…", "market_cap": 400_000_000_000_000, # 400 trillion KRW "shares_outstanding": 5_969_782_550, "establishment_date": "1969-01-13", "listing_date": "1975-06-11", "ceo_name": "이재용", "headquarters": "경기도 μˆ˜μ›μ‹œ μ˜ν†΅κ΅¬", "employee_count": 267_937, "main_products": ["λ°˜λ„μ²΄", "슀마트폰", "λ””μŠ€ν”Œλ ˆμ΄", "κ°€μ „μ œν’ˆ"] } @pytest.fixture def sample_financial_data(self): """Sample multi-year financial data""" return [ { "year": 2023, "revenue": 258_774_000_000_000, "operating_profit": 22_034_000_000_000, "net_profit": 15_349_000_000_000, "total_assets": 426_071_000_000_000, "total_equity": 319_167_000_000_000, "total_debt": 106_904_000_000_000, "operating_margin": 8.5, "net_margin": 5.9, "roe": 4.8, "roa": 3.6 }, { "year": 2022, "revenue": 302_231_000_000_000, "operating_profit": 43_376_000_000_000, "net_profit": 28_095_000_000_000, "total_assets": 399_653_000_000_000, "total_equity": 295_321_000_000_000, "total_debt": 104_332_000_000_000, "operating_margin": 14.4, "net_margin": 9.3, "roe": 9.5, "roa": 7.0 } ] @pytest.mark.asyncio async def test_get_enhanced_company_overview(self, company_analyzer, sample_company_data): """Test enhanced company overview with detailed information""" company_code = "005930" enhanced_overview = await company_analyzer.get_enhanced_company_overview( company_code=company_code, include_subsidiaries=True, include_recent_news=True, include_financial_highlights=True ) assert enhanced_overview is not None assert enhanced_overview["company_code"] == company_code assert "basic_info" in enhanced_overview assert "financial_highlights" in enhanced_overview assert "business_segments" in enhanced_overview assert "subsidiaries" in enhanced_overview assert "recent_news" in enhanced_overview assert "key_metrics" in enhanced_overview # Test financial highlights highlights = enhanced_overview["financial_highlights"] assert "revenue" in highlights assert "market_cap" in highlights assert "pe_ratio" in highlights assert "dividend_yield" in highlights @pytest.mark.asyncio async def test_calculate_financial_ratios(self, company_analyzer, sample_financial_data): """Test financial ratio calculations""" company_code = "005930" ratios = await company_analyzer.calculate_financial_ratios( company_code=company_code, years=3 ) assert ratios is not None assert "profitability" in ratios assert "liquidity" in ratios assert "leverage" in ratios assert "efficiency" in ratios assert "market" in ratios # Test profitability ratios profitability = ratios["profitability"] assert "operating_margin" in profitability assert "net_margin" in profitability assert "roe" in profitability assert "roa" in profitability assert "roic" in profitability # Validate ratio values are reasonable assert 0 <= profitability["operating_margin"] <= 100 assert 0 <= profitability["net_margin"] <= 100 assert profitability["roe"] > 0 @pytest.mark.asyncio async def test_get_business_segments(self, company_analyzer): """Test business segment analysis""" company_code = "005930" segments = await company_analyzer.get_business_segments(company_code) assert segments is not None assert isinstance(segments, list) assert len(segments) > 0 # Check segment structure segment = segments[0] assert "segment_name" in segment assert "revenue" in segment assert "operating_profit" in segment assert "revenue_ratio" in segment assert "profit_margin" in segment assert "yoy_growth" in segment # Test that revenue ratios sum to approximately 100% total_ratio = sum(s["revenue_ratio"] for s in segments) assert 95 <= total_ratio <= 105 # Allow some rounding error @pytest.mark.asyncio async def test_get_shareholder_information(self, company_analyzer): """Test shareholder information retrieval""" company_code = "005930" shareholders = await company_analyzer.get_shareholder_info(company_code) assert shareholders is not None assert "major_shareholders" in shareholders assert "ownership_structure" in shareholders assert "share_distribution" in shareholders # Test major shareholders major_shareholders = shareholders["major_shareholders"] assert isinstance(major_shareholders, list) assert len(major_shareholders) > 0 shareholder = major_shareholders[0] assert "shareholder_name" in shareholder assert "share_count" in shareholder assert "share_ratio" in shareholder assert "shareholder_type" in shareholder @pytest.mark.asyncio async def test_analyze_financial_trends(self, company_analyzer, sample_financial_data): """Test financial trend analysis""" company_code = "005930" trends = await company_analyzer.analyze_financial_trends( company_code=company_code, years=5 ) assert trends is not None assert "revenue_trend" in trends assert "profit_trend" in trends assert "margin_trend" in trends assert "growth_rates" in trends assert "trend_analysis" in trends # Test growth rates growth_rates = trends["growth_rates"] assert "revenue_cagr" in growth_rates assert "profit_cagr" in growth_rates assert "asset_growth" in growth_rates # Test trend analysis analysis = trends["trend_analysis"] assert "overall_trend" in analysis assert "key_insights" in analysis assert isinstance(analysis["key_insights"], list) @pytest.mark.asyncio async def test_compare_with_industry_averages(self, company_analyzer): """Test industry comparison functionality""" company_code = "005930" comparison = await company_analyzer.compare_with_industry( company_code=company_code, industry_code="26211" # Semiconductor manufacturing ) assert comparison is not None assert "company_metrics" in comparison assert "industry_averages" in comparison assert "comparison_analysis" in comparison assert "ranking" in comparison # Test comparison metrics company_metrics = comparison["company_metrics"] industry_averages = comparison["industry_averages"] for key in ["operating_margin", "net_margin", "roe", "debt_ratio"]: assert key in company_metrics assert key in industry_averages # Test ranking ranking = comparison["ranking"] assert "percentile" in ranking assert "industry_rank" in ranking assert 0 <= ranking["percentile"] <= 100 @pytest.mark.asyncio async def test_get_valuation_metrics(self, company_analyzer): """Test comprehensive valuation metrics""" company_code = "005930" valuation = await company_analyzer.get_valuation_metrics( company_code=company_code, include_peers=True ) assert valuation is not None assert "price_multiples" in valuation assert "enterprise_multiples" in valuation assert "dividend_metrics" in valuation assert "peer_comparison" in valuation assert "valuation_summary" in valuation # Test price multiples price_multiples = valuation["price_multiples"] expected_multiples = ["per", "pbr", "psr", "pcr", "pfr"] for multiple in expected_multiples: assert multiple in price_multiples assert price_multiples[multiple] > 0 @pytest.mark.asyncio async def test_error_handling_invalid_company(self, company_analyzer): """Test error handling for invalid company codes""" invalid_code = "999999" with pytest.raises(CompanyNotFoundError): await company_analyzer.get_enhanced_company_overview(invalid_code) @pytest.mark.asyncio async def test_error_handling_insufficient_data(self, company_analyzer): """Test handling when insufficient data is available""" # Test with a newly listed company that might not have full financial history new_company_code = "123456" # Hypothetical new listing with pytest.raises(InsufficientDataError): await company_analyzer.analyze_financial_trends( company_code=new_company_code, years=10 # Requesting more years than available ) class TestFinancialCalculator: """Test financial calculation utilities""" @pytest.fixture def calculator(self): """Create financial calculator instance""" return FinancialCalculator() @pytest.fixture def sample_financial_data(self): """Sample financial data for calculations""" return { "revenue": 258_774_000_000_000, "operating_profit": 22_034_000_000_000, "net_profit": 15_349_000_000_000, "total_assets": 426_071_000_000_000, "total_equity": 319_167_000_000_000, "total_debt": 106_904_000_000_000, "current_assets": 200_000_000_000_000, "current_liabilities": 80_000_000_000_000, "shares_outstanding": 5_969_782_550, "stock_price": 70_000 } def test_calculate_profitability_ratios(self, calculator, sample_financial_data): """Test profitability ratio calculations""" ratios = calculator.calculate_profitability_ratios(sample_financial_data) assert "operating_margin" in ratios assert "net_margin" in ratios assert "roe" in ratios assert "roa" in ratios assert "roic" in ratios # Validate calculations expected_operating_margin = (22_034_000_000_000 / 258_774_000_000_000) * 100 assert abs(ratios["operating_margin"] - expected_operating_margin) < 0.1 expected_roe = (15_349_000_000_000 / 319_167_000_000_000) * 100 assert abs(ratios["roe"] - expected_roe) < 0.1 def test_calculate_liquidity_ratios(self, calculator, sample_financial_data): """Test liquidity ratio calculations""" ratios = calculator.calculate_liquidity_ratios(sample_financial_data) assert "current_ratio" in ratios assert "quick_ratio" in ratios assert "cash_ratio" in ratios # Validate current ratio calculation expected_current_ratio = 200_000_000_000_000 / 80_000_000_000_000 assert abs(ratios["current_ratio"] - expected_current_ratio) < 0.1 def test_calculate_leverage_ratios(self, calculator, sample_financial_data): """Test leverage ratio calculations""" ratios = calculator.calculate_leverage_ratios(sample_financial_data) assert "debt_to_equity" in ratios assert "debt_to_assets" in ratios assert "equity_ratio" in ratios assert "interest_coverage" in ratios # Validate debt-to-equity calculation expected_dte = 106_904_000_000_000 / 319_167_000_000_000 assert abs(ratios["debt_to_equity"] - expected_dte) < 0.01 def test_calculate_market_ratios(self, calculator, sample_financial_data): """Test market ratio calculations""" ratios = calculator.calculate_market_ratios(sample_financial_data) assert "per" in ratios assert "pbr" in ratios assert "market_cap" in ratios assert "enterprise_value" in ratios # Validate market cap calculation expected_market_cap = 5_969_782_550 * 70_000 assert abs(ratios["market_cap"] - expected_market_cap) < 1000 def test_calculate_growth_rates(self, calculator): """Test growth rate calculations""" historical_data = [ {"year": 2021, "revenue": 200_000_000_000_000}, {"year": 2022, "revenue": 230_000_000_000_000}, {"year": 2023, "revenue": 258_774_000_000_000} ] growth_rates = calculator.calculate_growth_rates(historical_data, "revenue") assert "yoy_growth" in growth_rates assert "cagr" in growth_rates assert "average_growth" in growth_rates # CAGR should be positive for growing revenue assert growth_rates["cagr"] > 0 assert len(growth_rates["yoy_growth"]) == 2 # 2 year-over-year calculations def test_calculate_cagr(self, calculator): """Test CAGR calculation""" start_value = 100_000_000_000_000 end_value = 150_000_000_000_000 years = 3 cagr = calculator.calculate_cagr(start_value, end_value, years) # Manual verification: (150/100)^(1/3) - 1 β‰ˆ 14.47% expected_cagr = 14.47 assert abs(cagr - expected_cagr) < 0.1 def test_calculate_percentile_ranking(self, calculator): """Test percentile ranking calculation""" industry_values = [10, 15, 20, 25, 30, 35, 40] company_value = 28 percentile = calculator.calculate_percentile_ranking(company_value, industry_values) # 28 is at position 4 out of 7 positions (0-6), so 4/7 * 100 β‰ˆ 57.1% assert 55 <= percentile <= 60 if __name__ == "__main__": # Run tests with pytest pytest.main([__file__, "-v"])

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/whdghk1907/mcp-stock-details'

If you have feedback or need assistance with the MCP directory API, please join our Discord server