Skip to content

Commit 4bd890b

Browse files
Testcases
1 parent 984a6d3 commit 4bd890b

File tree

1 file changed

+220
-0
lines changed

1 file changed

+220
-0
lines changed
Lines changed: 220 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,220 @@
1+
import json
2+
import pytest
3+
from unittest.mock import AsyncMock, MagicMock, patch
4+
import os
5+
import sys
6+
7+
# Mock azure.monitor.events.extension globally
8+
sys.modules['azure.monitor.events.extension'] = MagicMock()
9+
10+
# Mock environment variables
11+
os.environ["COSMOSDB_ENDPOINT"] = "https://mock-endpoint"
12+
os.environ["COSMOSDB_KEY"] = "mock-key"
13+
os.environ["COSMOSDB_DATABASE"] = "mock-database"
14+
os.environ["COSMOSDB_CONTAINER"] = "mock-container"
15+
os.environ["AZURE_OPENAI_DEPLOYMENT_NAME"] = "mock-deployment-name"
16+
os.environ["AZURE_OPENAI_API_VERSION"] = "2023-01-01"
17+
os.environ["AZURE_OPENAI_ENDPOINT"] = "https://mock-openai-endpoint"
18+
19+
# Import PlannerAgent after setting mocks
20+
from src.backend.agents.planner import PlannerAgent
21+
from src.backend.models.messages import InputTask, HumanClarification, Plan, PlanStatus
22+
from src.backend.context.cosmos_memory import CosmosBufferedChatCompletionContext
23+
24+
25+
@pytest.fixture
26+
def mock_context():
27+
"""Mock the CosmosBufferedChatCompletionContext."""
28+
return MagicMock(spec=CosmosBufferedChatCompletionContext)
29+
30+
31+
@pytest.fixture
32+
def mock_model_client():
33+
"""Mock the Azure OpenAI model client."""
34+
return MagicMock()
35+
36+
37+
@pytest.fixture
38+
def mock_runtime_context():
39+
"""Mock the runtime context for AgentInstantiationContext."""
40+
with patch(
41+
"autogen_core.base._agent_instantiation.AgentInstantiationContext.AGENT_INSTANTIATION_CONTEXT_VAR",
42+
new=MagicMock(),
43+
) as mock_context_var:
44+
yield mock_context_var
45+
46+
47+
@pytest.fixture
48+
def planner_agent(mock_model_client, mock_context, mock_runtime_context):
49+
"""Return an instance of PlannerAgent with mocked dependencies."""
50+
# Mock the context variable to ensure runtime context is properly simulated
51+
mock_runtime_context.get.return_value = (MagicMock(), "mock-agent-id")
52+
return PlannerAgent(
53+
model_client=mock_model_client,
54+
session_id="test-session",
55+
user_id="test-user",
56+
memory=mock_context,
57+
available_agents=["HumanAgent", "MarketingAgent", "TechSupportAgent"],
58+
agent_tools_list=["tool1", "tool2"],
59+
)
60+
61+
@pytest.mark.asyncio
62+
async def test_handle_plan_clarification(planner_agent, mock_context):
63+
"""Test the handle_plan_clarification method."""
64+
# Prepare mock clarification and context
65+
mock_clarification = HumanClarification(
66+
session_id="test-session",
67+
plan_id="plan-1",
68+
human_clarification="Test clarification",
69+
)
70+
71+
mock_context.get_plan_by_session = AsyncMock(return_value=Plan(
72+
id="plan-1",
73+
session_id="test-session",
74+
user_id="test-user",
75+
initial_goal="Test Goal",
76+
overall_status="in_progress",
77+
source="PlannerAgent",
78+
summary="Mock Summary",
79+
human_clarification_request=None,
80+
))
81+
mock_context.update_plan = AsyncMock()
82+
mock_context.add_item = AsyncMock()
83+
84+
# Execute the method
85+
await planner_agent.handle_plan_clarification(mock_clarification, None)
86+
87+
# Assertions
88+
mock_context.get_plan_by_session.assert_called_with(session_id="test-session")
89+
mock_context.update_plan.assert_called()
90+
mock_context.add_item.assert_called()
91+
92+
@pytest.mark.asyncio
93+
async def test_generate_instruction_with_special_characters(planner_agent):
94+
"""Test _generate_instruction with special characters in the objective."""
95+
special_objective = "Solve this task: @$%^&*()"
96+
instruction = planner_agent._generate_instruction(special_objective)
97+
98+
# Assertions
99+
assert "Solve this task: @$%^&*()" in instruction
100+
assert "HumanAgent" in instruction
101+
assert "tool1" in instruction
102+
103+
104+
@pytest.mark.asyncio
105+
async def test_handle_plan_clarification_updates_plan_correctly(planner_agent, mock_context):
106+
"""Test handle_plan_clarification ensures correct plan updates."""
107+
mock_clarification = HumanClarification(
108+
session_id="test-session",
109+
plan_id="plan-1",
110+
human_clarification="Updated clarification text",
111+
)
112+
113+
mock_plan = Plan(
114+
id="plan-1",
115+
session_id="test-session",
116+
user_id="test-user",
117+
initial_goal="Test Goal",
118+
overall_status="in_progress",
119+
source="PlannerAgent",
120+
summary="Mock Summary",
121+
human_clarification_request="Previous clarification needed",
122+
)
123+
124+
# Mock get_plan_by_session and update_plan
125+
mock_context.get_plan_by_session = AsyncMock(return_value=mock_plan)
126+
mock_context.update_plan = AsyncMock()
127+
128+
# Execute the method
129+
await planner_agent.handle_plan_clarification(mock_clarification, None)
130+
131+
# Assertions
132+
assert mock_plan.human_clarification_response == "Updated clarification text"
133+
mock_context.update_plan.assert_called_with(mock_plan)
134+
135+
@pytest.mark.asyncio
136+
async def test_handle_input_task_with_exception(planner_agent, mock_context):
137+
"""Test handle_input_task gracefully handles exceptions."""
138+
# Mock InputTask
139+
input_task = InputTask(description="Test task causing exception", session_id="test-session")
140+
141+
# Mock _create_structured_plan to raise an exception
142+
planner_agent._create_structured_plan = AsyncMock(side_effect=Exception("Mocked exception"))
143+
144+
# Execute the method
145+
with pytest.raises(Exception, match="Mocked exception"):
146+
await planner_agent.handle_input_task(input_task, None)
147+
148+
# Assertions
149+
planner_agent._create_structured_plan.assert_called()
150+
mock_context.add_item.assert_not_called()
151+
mock_context.add_plan.assert_not_called()
152+
mock_context.add_step.assert_not_called()
153+
154+
@pytest.mark.asyncio
155+
async def test_handle_plan_clarification_handles_memory_error(planner_agent, mock_context):
156+
"""Test handle_plan_clarification gracefully handles memory errors."""
157+
mock_clarification = HumanClarification(
158+
session_id="test-session",
159+
plan_id="plan-1",
160+
human_clarification="Test clarification",
161+
)
162+
163+
# Mock get_plan_by_session to raise an exception
164+
mock_context.get_plan_by_session = AsyncMock(side_effect=Exception("Memory error"))
165+
166+
# Execute the method
167+
with pytest.raises(Exception, match="Memory error"):
168+
await planner_agent.handle_plan_clarification(mock_clarification, None)
169+
170+
# Ensure no updates or messages are added after failure
171+
mock_context.update_plan.assert_not_called()
172+
mock_context.add_item.assert_not_called()
173+
174+
175+
@pytest.mark.asyncio
176+
async def test_generate_instruction_with_missing_objective(planner_agent):
177+
"""Test _generate_instruction with a missing or empty objective."""
178+
instruction = planner_agent._generate_instruction("")
179+
assert "Your objective is:" in instruction
180+
assert "The agents you have access to are:" in instruction
181+
assert "These agents have access to the following functions:" in instruction
182+
183+
@pytest.mark.asyncio
184+
async def test_create_structured_plan_with_error(planner_agent, mock_context):
185+
"""Test _create_structured_plan when an error occurs during plan creation."""
186+
planner_agent._model_client.create = AsyncMock(side_effect=Exception("Mocked error"))
187+
188+
messages = [{"content": "Test message", "source": "PlannerAgent"}]
189+
plan, steps = await planner_agent._create_structured_plan(messages)
190+
191+
# Assertions
192+
assert plan.initial_goal == "Error generating plan"
193+
assert plan.overall_status == PlanStatus.failed
194+
assert len(steps) == 0
195+
mock_context.add_plan.assert_not_called()
196+
mock_context.add_step.assert_not_called()
197+
198+
@pytest.mark.asyncio
199+
async def test_create_structured_plan_with_multiple_steps(planner_agent, mock_context):
200+
"""Test _create_structured_plan with multiple steps."""
201+
planner_agent._model_client.create = AsyncMock(
202+
return_value=MagicMock(content=json.dumps({
203+
"initial_goal": "Task with multiple steps",
204+
"steps": [
205+
{"action": "Step 1", "agent": "HumanAgent"},
206+
{"action": "Step 2", "agent": "TechSupportAgent"},
207+
],
208+
"summary_plan_and_steps": "Generated summary with multiple steps",
209+
"human_clarification_request": None,
210+
}))
211+
)
212+
213+
messages = [{"content": "Test message", "source": "PlannerAgent"}]
214+
plan, steps = await planner_agent._create_structured_plan(messages)
215+
216+
# Assertions
217+
assert len(steps) == 2
218+
assert steps[0].action == "Step 1"
219+
assert steps[1].action == "Step 2"
220+
mock_context.add_step.assert_called()

0 commit comments

Comments
 (0)