|
1 | 1 | """ |
2 | | -Sample tests for AgentEx ACP agent. |
| 2 | +Tests for {{ agent_name }} |
3 | 3 |
|
4 | | -This test suite demonstrates how to test the main AgentEx API functions: |
5 | | -- Non-streaming event sending and polling |
6 | | -- Streaming event sending |
| 4 | +This test suite demonstrates testing your agentic agent with the AgentEx testing framework. |
7 | 5 |
|
8 | | -To run these tests: |
9 | | -1. Make sure the agent is running (via docker-compose or `agentex agents run`) |
10 | | -2. Set the AGENTEX_API_BASE_URL environment variable if not using default |
11 | | -3. Run: pytest test_agent.py -v |
| 6 | +Test coverage: |
| 7 | +- Basic event sending and polling |
| 8 | +- Streaming responses |
| 9 | +- Multi-turn conversations |
12 | 10 |
|
13 | | -Configuration: |
14 | | -- AGENTEX_API_BASE_URL: Base URL for the AgentEx server (default: http://localhost:5003) |
15 | | -- AGENT_NAME: Name of the agent to test (default: {{ agent_name }}) |
| 11 | +Prerequisites: |
| 12 | + - AgentEx services running (make dev) |
| 13 | + - Agent running: agentex agents run --manifest manifest.yaml |
| 14 | + |
| 15 | +Run tests: |
| 16 | + pytest tests/test_agent.py -v |
16 | 17 | """ |
17 | 18 |
|
18 | | -import os |
19 | | -import uuid |
20 | | -import asyncio |
21 | 19 | import pytest |
22 | | -import pytest_asyncio |
23 | | -from agentex import AsyncAgentex |
24 | | -from agentex.types import TaskMessage |
25 | | -from agentex.types.agent_rpc_params import ParamsCreateTaskRequest |
26 | | -from agentex.types.text_content_param import TextContentParam |
27 | | -from test_utils.agentic import ( |
28 | | - poll_for_agent_response, |
29 | | - send_event_and_poll_yielding, |
| 20 | + |
| 21 | +from agentex.lib.testing import ( |
| 22 | + test_agentic_agent, |
| 23 | + assert_valid_agent_response, |
| 24 | + assert_agent_response_contains, |
30 | 25 | stream_agent_response, |
31 | | - validate_text_in_response, |
32 | | - poll_messages, |
| 26 | + stream_task_messages, |
33 | 27 | ) |
34 | 28 |
|
| 29 | +AGENT_NAME = "{{ agent_name }}" |
| 30 | + |
| 31 | + |
| 32 | +@pytest.mark.asyncio |
| 33 | +async def test_agent_basic_response(): |
| 34 | + """Test that agent responds to basic events.""" |
| 35 | + async with test_agentic_agent(agent_name=AGENT_NAME) as test: |
| 36 | + response = await test.send_event( |
| 37 | + "Hello! Please respond briefly.", |
| 38 | + timeout_seconds=30.0 |
| 39 | + ) |
| 40 | + |
| 41 | + assert_valid_agent_response(response) |
| 42 | + assert len(response.content) > 0 |
| 43 | + print(f"✓ Agent responded: {response.content[:80]}...") |
| 44 | + |
| 45 | + |
| 46 | +@pytest.mark.asyncio |
| 47 | +async def test_agent_multi_turn(): |
| 48 | + """Test multi-turn conversation.""" |
| 49 | + async with test_agentic_agent(agent_name=AGENT_NAME) as test: |
| 50 | + # Turn 1 |
| 51 | + response1 = await test.send_event("Hello!", timeout_seconds=30.0) |
| 52 | + assert_valid_agent_response(response1) |
| 53 | + |
| 54 | + # Turn 2 |
| 55 | + response2 = await test.send_event("How are you?", timeout_seconds=30.0) |
| 56 | + assert_valid_agent_response(response2) |
| 57 | + |
| 58 | + # Turn 3 |
| 59 | + response3 = await test.send_event("Thank you!", timeout_seconds=30.0) |
| 60 | + assert_valid_agent_response(response3) |
| 61 | + |
| 62 | + # Verify history |
| 63 | + history = await test.get_conversation_history() |
| 64 | + assert len(history) >= 6, f"Expected >= 6 messages, got {len(history)}" |
| 65 | + print(f"✓ Conversation: {len(history)} messages") |
| 66 | + |
| 67 | + |
| 68 | +@pytest.mark.asyncio |
| 69 | +async def test_agent_streaming(): |
| 70 | + """Test streaming responses from agent.""" |
| 71 | + async with test_agentic_agent(agent_name=AGENT_NAME) as test: |
| 72 | + # Send event first |
| 73 | + await test.send_event("Start streaming task", timeout_seconds=10.0) |
| 74 | + |
| 75 | + # Now stream subsequent events |
| 76 | + events_received = [] |
| 77 | + async for event in test.send_event_and_stream("Stream this response", timeout_seconds=30.0): |
| 78 | + events_received.append(event) |
| 79 | + event_type = event.get('type') |
| 80 | + |
| 81 | + if event_type == 'done': |
| 82 | + print(f"✓ Stream complete ({len(events_received)} events)") |
| 83 | + break |
| 84 | + |
| 85 | + assert len(events_received) > 0, "Should receive at least one event" |
| 86 | + print(f"✓ Streaming works ({len(events_received)} events received)") |
| 87 | + |
| 88 | + |
| 89 | +@pytest.mark.asyncio |
| 90 | +async def test_agent_custom_scenario(): |
| 91 | + """ |
| 92 | + Add your custom test scenarios here. |
| 93 | + |
| 94 | + Customize this test for your agent's specific behavior and requirements. |
| 95 | + """ |
| 96 | + async with test_agentic_agent(agent_name=AGENT_NAME) as test: |
| 97 | + # Example: Test specific functionality |
| 98 | + response = await test.send_event( |
| 99 | + "Your custom test message here", |
| 100 | + timeout_seconds=30.0 |
| 101 | + ) |
| 102 | + |
| 103 | + assert_valid_agent_response(response) |
35 | 104 |
|
36 | | -# Configuration from environment variables |
37 | | -AGENTEX_API_BASE_URL = os.environ.get("AGENTEX_API_BASE_URL", "http://localhost:5003") |
38 | | -AGENT_NAME = os.environ.get("AGENT_NAME", "{{ agent_name }}") |
39 | | - |
40 | | - |
41 | | -@pytest_asyncio.fixture |
42 | | -async def client(): |
43 | | - """Create an AsyncAgentex client instance for testing.""" |
44 | | - client = AsyncAgentex(base_url=AGENTEX_API_BASE_URL) |
45 | | - yield client |
46 | | - await client.close() |
47 | | - |
48 | | - |
49 | | -@pytest.fixture |
50 | | -def agent_name(): |
51 | | - """Return the agent name for testing.""" |
52 | | - return AGENT_NAME |
53 | | - |
54 | | - |
55 | | -@pytest_asyncio.fixture |
56 | | -async def agent_id(client, agent_name): |
57 | | - """Retrieve the agent ID based on the agent name.""" |
58 | | - agents = await client.agents.list() |
59 | | - for agent in agents: |
60 | | - if agent.name == agent_name: |
61 | | - return agent.id |
62 | | - raise ValueError(f"Agent with name {agent_name} not found.") |
63 | | - |
64 | | - |
65 | | -class TestNonStreamingEvents: |
66 | | - """Test non-streaming event sending and polling.""" |
67 | | - |
68 | | - @pytest.mark.asyncio |
69 | | - async def test_send_event_and_poll(self, client: AsyncAgentex, _agent_name: str, agent_id: str): |
70 | | - """Test sending an event and polling for the response.""" |
71 | | - # TODO: Create a task for this conversation |
72 | | - # task_response = await client.agents.create_task(agent_id, params=ParamsCreateTaskRequest(name=uuid.uuid1().hex)) |
73 | | - # task = task_response.result |
74 | | - # assert task is not None |
75 | | - |
76 | | - # TODO: Poll for the initial task creation message (if your agent sends one) |
77 | | - # async for message in poll_messages( |
78 | | - # client=client, |
79 | | - # task_id=task.id, |
80 | | - # timeout=30, |
81 | | - # sleep_interval=1.0, |
82 | | - # ): |
83 | | - # assert isinstance(message, TaskMessage) |
84 | | - # if message.content and message.content.type == "text" and message.content.author == "agent": |
85 | | - # # Check for your expected initial message |
86 | | - # assert "expected initial text" in message.content.content |
87 | | - # break |
88 | | - |
89 | | - # TODO: Send an event and poll for response using the yielding helper function |
90 | | - # user_message = "Your test message here" |
91 | | - # async for message in send_event_and_poll_yielding( |
92 | | - # client=client, |
93 | | - # agent_id=agent_id, |
94 | | - # task_id=task.id, |
95 | | - # user_message=user_message, |
96 | | - # timeout=30, |
97 | | - # sleep_interval=1.0, |
98 | | - # ): |
99 | | - # assert isinstance(message, TaskMessage) |
100 | | - # if message.content and message.content.type == "text" and message.content.author == "agent": |
101 | | - # # Check for your expected response |
102 | | - # assert "expected response text" in message.content.content |
103 | | - # break |
104 | | - pass |
105 | | - |
106 | | - |
107 | | -class TestStreamingEvents: |
108 | | - """Test streaming event sending.""" |
109 | | - |
110 | | - @pytest.mark.asyncio |
111 | | - async def test_send_event_and_stream(self, client: AsyncAgentex, _agent_name: str, agent_id: str): |
112 | | - """Test sending an event and streaming the response.""" |
113 | | - # TODO: Create a task for this conversation |
114 | | - # task_response = await client.agents.create_task(agent_id, params=ParamsCreateTaskRequest(name=uuid.uuid1().hex)) |
115 | | - # task = task_response.result |
116 | | - # assert task is not None |
117 | | - |
118 | | - # user_message = "Your test message here" |
119 | | - |
120 | | - # # Collect events from stream |
121 | | - # all_events = [] |
122 | | - |
123 | | - # async def collect_stream_events(): |
124 | | - # async for event in stream_agent_response( |
125 | | - # client=client, |
126 | | - # task_id=task.id, |
127 | | - # timeout=30, |
128 | | - # ): |
129 | | - # all_events.append(event) |
130 | | - |
131 | | - # # Start streaming task |
132 | | - # stream_task = asyncio.create_task(collect_stream_events()) |
133 | | - |
134 | | - # # Send the event |
135 | | - # event_content = TextContentParam(type="text", author="user", content=user_message) |
136 | | - # await client.agents.send_event(agent_id=agent_id, params={"task_id": task.id, "content": event_content}) |
137 | | - |
138 | | - # # Wait for streaming to complete |
139 | | - # await stream_task |
140 | | - |
141 | | - # # TODO: Add your validation here |
142 | | - # assert len(all_events) > 0, "No events received in streaming response" |
143 | | - pass |
| 105 | + # Add assertions specific to your agent's expected behavior |
| 106 | + # assert_agent_response_contains(response, "expected text") |
| 107 | + # assert len(response.content) > 100, "Response should be detailed" |
144 | 108 |
|
145 | 109 |
|
146 | 110 | if __name__ == "__main__": |
147 | | - pytest.main([__file__, "-v"]) |
| 111 | + print(f"Run with: pytest tests/test_agent.py -v") |
| 112 | + print(f"Testing agent: {AGENT_NAME}") |
0 commit comments