Skip to content

Commit 586b6d9

Browse files
linting and jinja2
1 parent 2185974 commit 586b6d9

File tree

13 files changed

+292
-42
lines changed

13 files changed

+292
-42
lines changed

examples/tutorials/20_behavior_testing/000_basic_sync_testing/test_sync_agent.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@
1717
"""
1818

1919
from agentex.lib.testing import (
20+
test_sync_agent,
21+
assert_valid_agent_response,
2022
assert_agent_response_contains,
2123
assert_conversation_maintains_context,
22-
assert_valid_agent_response,
23-
test_sync_agent,
2424
)
2525

2626
# TODO: Replace with your actual sync agent name from 'agentex agents list'

examples/tutorials/20_behavior_testing/010_agentic_testing/test_agentic_agent.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818

1919
import pytest
2020

21-
from agentex.lib.testing import assert_valid_agent_response, test_agentic_agent
21+
from agentex.lib.testing import test_agentic_agent, assert_valid_agent_response
2222

2323
# TODO: Replace with your actual agent name from 'agentex agents list'
2424
AGENT_NAME = "ab000-hello-acp"

src/agentex/lib/cli/commands/init.py

Lines changed: 16 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from __future__ import annotations
2+
13
from enum import Enum
24
from typing import Any, Dict
35
from pathlib import Path
@@ -23,18 +25,14 @@ class TemplateType(str, Enum):
2325
SYNC = "sync"
2426

2527

26-
def render_template(
27-
template_path: str, context: Dict[str, Any], template_type: TemplateType
28-
) -> str:
28+
def render_template(template_path: str, context: Dict[str, Any], template_type: TemplateType) -> str:
2929
"""Render a template with the given context"""
3030
env = Environment(loader=FileSystemLoader(TEMPLATES_DIR / template_type.value))
3131
template = env.get_template(template_path)
3232
return template.render(**context)
3333

3434

35-
def create_project_structure(
36-
path: Path, context: Dict[str, Any], template_type: TemplateType, use_uv: bool
37-
):
35+
def create_project_structure(path: Path, context: Dict[str, Any], template_type: TemplateType, use_uv: bool):
3836
"""Create the project structure from templates"""
3937
# Create project directory
4038
project_dir: Path = path / context["project_name"]
@@ -79,6 +77,9 @@ def create_project_structure(
7977
# Add development notebook for agents
8078
root_templates["dev.ipynb.j2"] = "dev.ipynb"
8179

80+
# Add test file
81+
root_templates["test_agent.py.j2"] = "test_agent.py"
82+
8283
for template, output in root_templates.items():
8384
output_path = project_dir / output
8485
output_path.write_text(render_template(template, context, template_type))
@@ -97,10 +98,7 @@ def get_project_context(answers: Dict[str, Any], project_path: Path, manifest_ro
9798
return {
9899
**answers,
99100
"project_name": project_name,
100-
"workflow_class": "".join(
101-
word.capitalize() for word in answers["agent_name"].split("-")
102-
)
103-
+ "Workflow",
101+
"workflow_class": "".join(word.capitalize() for word in answers["agent_name"].split("-")) + "Workflow",
104102
"workflow_name": answers["agent_name"],
105103
"queue_name": project_name + "_queue",
106104
"project_path_from_build_root": project_path_from_build_root,
@@ -155,9 +153,7 @@ def validate_agent_name(text: str) -> bool | str:
155153
if not template_type:
156154
return
157155

158-
project_path = questionary.path(
159-
"Where would you like to create your project?", default="."
160-
).ask()
156+
project_path = questionary.path("Where would you like to create your project?", default=".").ask()
161157
if not project_path:
162158
return
163159

@@ -175,9 +171,7 @@ def validate_agent_name(text: str) -> bool | str:
175171
if not agent_directory_name:
176172
return
177173

178-
description = questionary.text(
179-
"Provide a brief description of your agent:", default="An AgentEx agent"
180-
).ask()
174+
description = questionary.text("Provide a brief description of your agent:", default="An AgentEx agent").ask()
181175
if not description:
182176
return
183177

@@ -208,9 +202,7 @@ def validate_agent_name(text: str) -> bool | str:
208202
context["use_uv"] = answers["use_uv"]
209203

210204
# Create project structure
211-
create_project_structure(
212-
project_path, context, answers["template_type"], answers["use_uv"]
213-
)
205+
create_project_structure(project_path, context, answers["template_type"], answers["use_uv"])
214206

215207
# Show next steps
216208
console.print("\n[bold green]✨ Project created successfully![/bold green]")
@@ -226,7 +218,8 @@ def validate_agent_name(text: str) -> bool | str:
226218
console.print("4. Run locally:")
227219
console.print(" agentex agents run --manifest manifest.yaml")
228220

229-
console.print("5. Deploy your agent:")
230-
console.print(
231-
" agentex agents deploy --cluster your-cluster --namespace your-namespace"
232-
)
221+
console.print("5. Test your agent:")
222+
console.print(" pytest test_agent.py -v")
223+
224+
console.print("6. Deploy your agent:")
225+
console.print(" agentex agents deploy --cluster your-cluster --namespace your-namespace")
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
"""
2+
Tests for {{ agent_name }} agent
3+
4+
This file provides basic behavior tests for your agent using the AgentEx testing framework.
5+
6+
Prerequisites:
7+
- AgentEx services running (make dev)
8+
- Agent running: agentex agents run --manifest manifest.yaml
9+
10+
Run tests:
11+
pytest test_agent.py -v
12+
"""
13+
14+
import pytest
15+
16+
from agentex.lib.testing import (
17+
test_agentic_agent,
18+
assert_valid_agent_response,
19+
assert_agent_response_contains,
20+
)
21+
22+
AGENT_NAME = "{{ agent_name }}"
23+
24+
25+
@pytest.mark.asyncio
26+
async def test_agent_responds():
27+
"""Test that agent responds to basic messages."""
28+
async with test_agentic_agent(agent_name=AGENT_NAME) as test:
29+
response = await test.send_event(
30+
"Hello! Please respond briefly.",
31+
timeout_seconds=30.0
32+
)
33+
34+
assert_valid_agent_response(response)
35+
assert len(response.content) > 0
36+
print(f"✓ Agent responded: {response.content[:80]}...")
37+
38+
39+
@pytest.mark.asyncio
40+
async def test_agent_multi_turn():
41+
"""Test that agent handles multi-turn conversation."""
42+
async with test_agentic_agent(agent_name=AGENT_NAME) as test:
43+
# Turn 1
44+
response1 = await test.send_event("Hello!", timeout_seconds=30.0)
45+
assert_valid_agent_response(response1)
46+
47+
# Turn 2
48+
response2 = await test.send_event("Thank you!", timeout_seconds=30.0)
49+
assert_valid_agent_response(response2)
50+
51+
# Verify history
52+
history = await test.get_conversation_history()
53+
assert len(history) >= 4 # 2 user + 2 agent messages
54+
print(f"✓ Conversation: {len(history)} messages")
55+
56+
57+
@pytest.mark.asyncio
58+
async def test_agent_custom_scenario():
59+
"""
60+
Add your custom test scenarios here.
61+
62+
Example: Test specific functionality of your agent
63+
"""
64+
async with test_agentic_agent(agent_name=AGENT_NAME) as test:
65+
# Customize this test for your agent's specific behavior
66+
response = await test.send_event(
67+
"Your custom test message here",
68+
timeout_seconds=30.0
69+
)
70+
71+
assert_valid_agent_response(response)
72+
73+
# Add assertions specific to your agent's expected behavior
74+
# assert_agent_response_contains(response, "expected text")
75+
76+
77+
if __name__ == "__main__":
78+
print(f"Run with: pytest test_agent.py -v")
79+
print(f"Testing agent: {AGENT_NAME}")
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
"""
2+
Tests for {{ agent_name }} sync agent
3+
4+
This file provides basic behavior tests for your sync agent using the AgentEx testing framework.
5+
6+
Prerequisites:
7+
- AgentEx services running (make dev)
8+
- Agent running: agentex agents run --manifest manifest.yaml
9+
10+
Run tests:
11+
pytest test_agent.py -v
12+
"""
13+
14+
from agentex.lib.testing import (
15+
test_sync_agent,
16+
assert_valid_agent_response,
17+
assert_agent_response_contains,
18+
)
19+
20+
AGENT_NAME = "{{ agent_name }}"
21+
22+
23+
def test_agent_responds():
24+
"""Test that sync agent responds to basic messages."""
25+
with test_sync_agent(agent_name=AGENT_NAME) as test:
26+
response = test.send_message("Hello! Please respond briefly.")
27+
28+
assert_valid_agent_response(response)
29+
assert len(response.content) > 0
30+
print(f"✓ Agent responded: {response.content[:80]}...")
31+
32+
33+
def test_agent_multi_turn():
34+
"""Test that sync agent handles multi-turn conversation."""
35+
with test_sync_agent(agent_name=AGENT_NAME) as test:
36+
# Turn 1
37+
response1 = test.send_message("Hello!")
38+
assert_valid_agent_response(response1)
39+
40+
# Turn 2
41+
response2 = test.send_message("How are you?")
42+
assert_valid_agent_response(response2)
43+
44+
# Turn 3
45+
response3 = test.send_message("Thank you!")
46+
assert_valid_agent_response(response3)
47+
48+
# Verify history
49+
history = test.get_conversation_history()
50+
assert len(history) >= 6 # 3 user + 3 agent messages
51+
print(f"✓ Conversation: {len(history)} messages")
52+
53+
54+
def test_agent_custom_scenario():
55+
"""
56+
Add your custom test scenarios here.
57+
58+
Example: Test specific functionality of your sync agent
59+
"""
60+
with test_sync_agent(agent_name=AGENT_NAME) as test:
61+
# Customize this test for your agent's specific behavior
62+
response = test.send_message("Your custom test message here")
63+
64+
assert_valid_agent_response(response)
65+
66+
# Add assertions specific to your agent's expected behavior
67+
# assert_agent_response_contains(response, "expected text")
68+
69+
70+
if __name__ == "__main__":
71+
print(f"Run with: pytest test_agent.py -v")
72+
print(f"Testing agent: {AGENT_NAME}")
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
"""
2+
Tests for {{ agent_name }} temporal agent
3+
4+
This file provides basic behavior tests for your temporal agent using the AgentEx testing framework.
5+
6+
Prerequisites:
7+
- AgentEx services running (make dev)
8+
- Temporal server running
9+
- Agent running: agentex agents run --manifest manifest.yaml
10+
11+
Run tests:
12+
pytest test_agent.py -v
13+
14+
Note: Temporal agents may need longer timeouts due to workflow orchestration overhead.
15+
"""
16+
17+
import pytest
18+
19+
from agentex.lib.testing import (
20+
test_agentic_agent,
21+
assert_valid_agent_response,
22+
assert_agent_response_contains,
23+
)
24+
25+
AGENT_NAME = "{{ agent_name }}"
26+
27+
28+
@pytest.mark.asyncio
29+
async def test_agent_responds():
30+
"""Test that agent responds to basic messages."""
31+
async with test_agentic_agent(agent_name=AGENT_NAME) as test:
32+
response = await test.send_event(
33+
"Hello! Please respond briefly.",
34+
timeout_seconds=60.0 # Temporal agents may need more time
35+
)
36+
37+
assert_valid_agent_response(response)
38+
assert len(response.content) > 0
39+
print(f"✓ Agent responded: {response.content[:80]}...")
40+
41+
42+
@pytest.mark.asyncio
43+
async def test_agent_multi_turn():
44+
"""Test that agent handles multi-turn conversation."""
45+
async with test_agentic_agent(agent_name=AGENT_NAME) as test:
46+
# Turn 1
47+
response1 = await test.send_event("Hello!", timeout_seconds=60.0)
48+
assert_valid_agent_response(response1)
49+
50+
# Turn 2
51+
response2 = await test.send_event("How are you?", timeout_seconds=60.0)
52+
assert_valid_agent_response(response2)
53+
54+
# Turn 3
55+
response3 = await test.send_event("Thank you!", timeout_seconds=60.0)
56+
assert_valid_agent_response(response3)
57+
58+
# Verify history
59+
history = await test.get_conversation_history()
60+
assert len(history) >= 6 # 3 user + 3 agent messages
61+
print(f"✓ Conversation: {len(history)} messages")
62+
63+
64+
@pytest.mark.asyncio
65+
async def test_agent_workflow_execution():
66+
"""
67+
Test your temporal workflow execution.
68+
69+
Temporal agents can handle long-running tasks with retries and state management.
70+
Adjust timeout based on your workflow's expected duration.
71+
"""
72+
async with test_agentic_agent(agent_name=AGENT_NAME) as test:
73+
response = await test.send_event(
74+
"Execute your workflow task here",
75+
timeout_seconds=120.0 # Longer timeout for complex workflows
76+
)
77+
78+
assert_valid_agent_response(response)
79+
80+
# Add assertions specific to your workflow's expected behavior
81+
# assert_agent_response_contains(response, "workflow completed")
82+
83+
84+
@pytest.mark.asyncio
85+
async def test_agent_custom_scenario():
86+
"""
87+
Add your custom test scenarios here.
88+
89+
Example: Test specific functionality of your temporal agent
90+
"""
91+
async with test_agentic_agent(agent_name=AGENT_NAME) as test:
92+
# Customize this test for your agent's specific behavior
93+
response = await test.send_event(
94+
"Your custom test message here",
95+
timeout_seconds=60.0
96+
)
97+
98+
assert_valid_agent_response(response)
99+
100+
# Add assertions specific to your agent's expected behavior
101+
# assert_agent_response_contains(response, "expected text")
102+
103+
104+
if __name__ == "__main__":
105+
print(f"Run with: pytest test_agent.py -v")
106+
print(f"Testing agent: {AGENT_NAME}")
107+
print("\nNote: Temporal agents may require longer timeouts")

src/agentex/lib/testing/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,9 @@ async def test_my_agentic_agent():
4646
assert_conversation_maintains_context,
4747
)
4848
from agentex.lib.testing.exceptions import (
49+
AgentTimeoutError,
4950
AgentNotFoundError,
5051
AgentSelectionError,
51-
AgentTimeoutError,
5252
)
5353

5454
__all__ = [

src/agentex/lib/testing/config.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
Centralized configuration management with environment variable support.
55
"""
66

7-
import logging
87
import os
8+
import logging
99
from dataclasses import dataclass
1010

1111
logger = logging.getLogger(__name__)

0 commit comments

Comments
 (0)