test_business_segments.pyβ’12.6 kB
"""
Unit tests for Business Segments functionality
TDD Red Phase: Write failing tests for business segment analysis
"""
import pytest
import asyncio
from unittest.mock import Mock, AsyncMock, patch
from datetime import datetime, date, timedelta
from typing import Any, Dict, List, Optional
# Test imports - initially will fail (TDD Red phase)
from src.server import MCPStockDetailsServer
from src.tools.business_segment_tools import BusinessSegmentAnalyzer
from src.exceptions import MCPStockDetailsError, InsufficientDataError
class TestBusinessSegments:
"""Test cases for business segments functionality"""
@pytest.fixture
def server_with_segments(self):
"""Create server instance with business segment analyzer"""
server = MCPStockDetailsServer()
# This will fail initially - Red phase
server.business_segment_analyzer = BusinessSegmentAnalyzer()
return server
@pytest.fixture
def sample_segment_data(self):
"""Sample business segment data for testing"""
return {
"005930": { # Samsung Electronics
"segments": [
{
"name": "λ°λ체",
"revenue_2023": 63747000000000,
"revenue_2022": 76956000000000,
"revenue_2021": 83018000000000,
"operating_profit_2023": 3369000000000,
"operating_profit_2022": 18325000000000,
"assets": 145632000000000,
"percentage_of_total": 25.8
},
{
"name": "λμ€νλ μ΄ν¨λ",
"revenue_2023": 50148000000000,
"revenue_2022": 47543000000000,
"revenue_2021": 45897000000000,
"operating_profit_2023": 1561000000000,
"operating_profit_2022": 1204000000000,
"assets": 82451000000000,
"percentage_of_total": 20.3
},
{
"name": "IM(λͺ¨λ°μΌ)",
"revenue_2023": 124871000000000,
"revenue_2022": 118345000000000,
"revenue_2021": 109385000000000,
"operating_profit_2023": 8952000000000,
"operating_profit_2022": 7825000000000,
"assets": 67234000000000,
"percentage_of_total": 50.5
},
{
"name": "κΈ°ν",
"revenue_2023": 8908000000000,
"revenue_2022": 9128000000000,
"revenue_2021": 8745000000000,
"operating_profit_2023": 421000000000,
"operating_profit_2022": 392000000000,
"assets": 12851000000000,
"percentage_of_total": 3.4
}
],
"geographic_segments": [
{"region": "νκ΅", "revenue": 75234000000000, "percentage": 30.4},
{"region": "μ€κ΅", "revenue": 58967000000000, "percentage": 23.9},
{"region": "λ―Έκ΅", "revenue": 68453000000000, "percentage": 27.7},
{"region": "μ λ½", "revenue": 25129000000000, "percentage": 10.2},
{"region": "κΈ°ν", "revenue": 19091000000000, "percentage": 7.8}
],
"total_revenue_2023": 247674000000000,
"total_revenue_2022": 251972000000000,
"total_revenue_2021": 256387000000000
}
}
@pytest.mark.asyncio
async def test_get_business_segments_tool_registration(self, server_with_segments):
"""Test that get_business_segments tool is properly registered"""
tools = await server_with_segments.list_tools()
tool_names = [tool.name for tool in tools]
assert "get_business_segments" in tool_names
# Check tool description and parameters
segments_tool = next(tool for tool in tools if tool.name == "get_business_segments")
assert "business" in segments_tool.description.lower()
assert "segment" in segments_tool.description.lower()
assert "company_code" in segments_tool.inputSchema["properties"]
@pytest.mark.asyncio
async def test_business_segment_analysis(self, server_with_segments, sample_segment_data):
"""Test business segment analysis"""
company_code = "005930"
with patch.object(server_with_segments.business_segment_analyzer, 'get_segment_data') as mock_data:
mock_data.return_value = sample_segment_data[company_code]
result = await server_with_segments._handle_get_business_segments({
"company_code": company_code,
"include_revenue_breakdown": True
})
assert result is not None
assert len(result) > 0
content = result[0].text
# Should include business segments
assert "BUSINESS SEGMENTS" in content
assert "λ°λ체" in content
assert "λμ€νλ μ΄ν¨λ" in content
assert "IM(λͺ¨λ°μΌ)" in content
assert "25.8%" in content
assert "50.5%" in content
@pytest.mark.asyncio
async def test_segment_performance_analysis(self, server_with_segments, sample_segment_data):
"""Test segment performance analysis"""
company_code = "005930"
with patch.object(server_with_segments.business_segment_analyzer, 'get_segment_data') as mock_data:
mock_data.return_value = sample_segment_data[company_code]
result = await server_with_segments._handle_get_business_segments({
"company_code": company_code,
"include_performance_analysis": True
})
assert result is not None
content = result[0].text
# Should include performance analysis
assert "SEGMENT PERFORMANCE" in content
assert "Operating Profit" in content
assert "Growth Rate" in content
assert "Margin Analysis" in content
@pytest.mark.asyncio
async def test_geographic_segment_analysis(self, server_with_segments, sample_segment_data):
"""Test geographic segment analysis"""
company_code = "005930"
with patch.object(server_with_segments.business_segment_analyzer, 'get_segment_data') as mock_data:
mock_data.return_value = sample_segment_data[company_code]
result = await server_with_segments._handle_get_business_segments({
"company_code": company_code,
"include_geographic_analysis": True
})
assert result is not None
content = result[0].text
# Should include geographic analysis
assert "GEOGRAPHIC SEGMENTS" in content
assert "νκ΅" in content
assert "μ€κ΅" in content
assert "λ―Έκ΅" in content
assert "30.4%" in content
assert "23.9%" in content
@pytest.mark.asyncio
async def test_segment_growth_analysis(self, server_with_segments, sample_segment_data):
"""Test segment growth analysis"""
company_code = "005930"
result = await server_with_segments._handle_get_business_segments({
"company_code": company_code,
"include_growth_analysis": True,
"analysis_period": "3Y"
})
assert result is not None
content = result[0].text
# Should include growth analysis
assert "GROWTH ANALYSIS" in content
assert "CAGR" in content or "Growth Rate" in content
assert "Trend Analysis" in content
@pytest.mark.asyncio
async def test_segment_profitability_analysis(self, server_with_segments, sample_segment_data):
"""Test segment profitability analysis"""
company_code = "005930"
result = await server_with_segments._handle_get_business_segments({
"company_code": company_code,
"include_profitability_analysis": True
})
assert result is not None
content = result[0].text
# Should include profitability analysis
assert "PROFITABILITY ANALYSIS" in content
assert "Operating Margin" in content
assert "ROA" in content or "Return on Assets" in content
assert "Segment Efficiency" in content
@pytest.mark.asyncio
async def test_segment_risk_analysis(self, server_with_segments):
"""Test segment risk analysis"""
company_code = "005930"
result = await server_with_segments._handle_get_business_segments({
"company_code": company_code,
"include_risk_analysis": True
})
assert result is not None
content = result[0].text
# Should include risk analysis
assert "SEGMENT RISK" in content
assert "Concentration Risk" in content
assert "Market Risk" in content
assert "Diversification" in content
@pytest.mark.asyncio
async def test_competitive_positioning_analysis(self, server_with_segments):
"""Test competitive positioning analysis"""
company_code = "005930"
result = await server_with_segments._handle_get_business_segments({
"company_code": company_code,
"include_competitive_analysis": True
})
assert result is not None
content = result[0].text
# Should include competitive analysis
assert "COMPETITIVE POSITIONING" in content
assert "Market Share" in content
assert "Competitive Advantage" in content
@pytest.mark.asyncio
async def test_comprehensive_segment_report(self, server_with_segments, sample_segment_data):
"""Test comprehensive segment report generation"""
company_code = "005930"
with patch.object(server_with_segments.business_segment_analyzer, 'get_segment_data') as mock_data:
mock_data.return_value = sample_segment_data[company_code]
result = await server_with_segments._handle_get_business_segments({
"company_code": company_code,
"analysis_type": "comprehensive"
})
assert result is not None
content = result[0].text
# Should include comprehensive analysis
assert "COMPREHENSIVE BUSINESS ANALYSIS" in content
assert "Segment Overview" in content
assert "Strategic Assessment" in content
assert "Key Insights" in content
@pytest.mark.asyncio
async def test_segment_trend_analysis(self, server_with_segments, sample_segment_data):
"""Test segment trend analysis"""
company_code = "005930"
result = await server_with_segments._handle_get_business_segments({
"company_code": company_code,
"include_trend_analysis": True,
"trend_period": "5Y"
})
assert result is not None
content = result[0].text
# Should include trend analysis
assert "TREND ANALYSIS" in content
assert "Historical Performance" in content
assert "Future Outlook" in content
@pytest.mark.asyncio
async def test_business_segments_error_handling(self, server_with_segments):
"""Test error handling for business segments"""
# Test invalid company code
with pytest.raises(MCPStockDetailsError):
await server_with_segments._handle_get_business_segments({
"company_code": "",
"include_revenue_breakdown": True
})
# Test insufficient segment data
with pytest.raises(InsufficientDataError):
await server_with_segments._handle_get_business_segments({
"company_code": "999999", # Non-existent company
"include_revenue_breakdown": True
})