test: 更新 AgentScope 相关单元测试与集成测试
- 重命名 test_react_runner.py 为 test_runner.py - 新增 test_utils.py 测试工具函数 - 更新现有测试用例适配新架构
This commit is contained in:
@@ -3,23 +3,6 @@ from __future__ import annotations
|
||||
from core.agentscope.events.agui_codec import to_agui_wire_event
|
||||
|
||||
|
||||
def test_maps_internal_text_delta_to_agui_wire_event() -> None:
|
||||
internal = {
|
||||
"id": "e1",
|
||||
"type": "text.delta",
|
||||
"threadId": "t1",
|
||||
"runId": "r1",
|
||||
"data": {"delta": "hel"},
|
||||
}
|
||||
|
||||
result = to_agui_wire_event(internal)
|
||||
|
||||
assert result["type"] == "TEXT_MESSAGE_CONTENT"
|
||||
assert result["threadId"] == "t1"
|
||||
assert result["runId"] == "r1"
|
||||
assert result["delta"] == "hel"
|
||||
|
||||
|
||||
def test_reserved_keys_in_data_cannot_override_wire_fields() -> None:
|
||||
internal = {
|
||||
"id": "e2",
|
||||
@@ -42,24 +25,21 @@ def test_reserved_keys_in_data_cannot_override_wire_fields() -> None:
|
||||
assert result["message"] == "ok"
|
||||
|
||||
|
||||
def test_tool_result_wire_event_filters_sensitive_fields() -> None:
|
||||
def test_tool_result_wire_event_with_bare_fields() -> None:
|
||||
internal = {
|
||||
"type": "tool.result",
|
||||
"threadId": "thread-1",
|
||||
"runId": "run-1",
|
||||
"data": {
|
||||
"messageId": "tool-result-1",
|
||||
"toolCallId": "call-1",
|
||||
"toolAgentOutput": {
|
||||
"tool_name": "calendar_write",
|
||||
"tool_call_id": "call-1",
|
||||
"status": "success",
|
||||
"result_summary": "summary",
|
||||
"tool_call_args": {},
|
||||
},
|
||||
"args": {"token": "secret"},
|
||||
"result": {"raw": "secret"},
|
||||
"error": "stack trace",
|
||||
"role": "tool",
|
||||
"stage": "worker",
|
||||
"tool_name": "calendar_write",
|
||||
"tool_call_id": "call-1",
|
||||
"tool_call_args": {"start_date": "2024-01-01"},
|
||||
"status": "success",
|
||||
"result_summary": "summary",
|
||||
"ui_schema": {"version": "2.0"},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -67,25 +47,32 @@ def test_tool_result_wire_event_filters_sensitive_fields() -> None:
|
||||
|
||||
assert result["type"] == "TOOL_CALL_RESULT"
|
||||
assert result["messageId"] == "tool-result-1"
|
||||
assert result["toolCallId"] == "call-1"
|
||||
assert isinstance(result.get("toolAgentOutput"), dict)
|
||||
assert "args" not in result
|
||||
assert "result" not in result
|
||||
assert "error" not in result
|
||||
assert result["tool_name"] == "calendar_write"
|
||||
assert result["tool_call_id"] == "call-1"
|
||||
assert result["status"] == "success"
|
||||
assert result["result_summary"] == "summary"
|
||||
assert result["ui_schema"] == {"version": "2.0"}
|
||||
|
||||
|
||||
def test_text_end_event_only_keeps_protocol_fields() -> None:
|
||||
def test_text_end_event_with_bare_fields() -> None:
|
||||
internal = {
|
||||
"type": "text.end",
|
||||
"threadId": "thread-1",
|
||||
"runId": "run-1",
|
||||
"data": {
|
||||
"messageId": "assistant-run-1",
|
||||
"workerAgentOutput": {"answer": "done", "status": "success"},
|
||||
"role": "assistant",
|
||||
"stage": "worker",
|
||||
"model": "qwen",
|
||||
"inputTokens": 1,
|
||||
"outputTokens": 2,
|
||||
"status": "success",
|
||||
"answer": "done",
|
||||
"key_points": ["point1"],
|
||||
"result_type": "execution_report",
|
||||
"suggested_actions": ["action1"],
|
||||
"ui_schema": {"version": "2.0"},
|
||||
"inputTokens": 100,
|
||||
"outputTokens": 50,
|
||||
"cost": 0.01,
|
||||
"latencyMs": 1000,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -93,7 +80,113 @@ def test_text_end_event_only_keeps_protocol_fields() -> None:
|
||||
|
||||
assert result["type"] == "TEXT_MESSAGE_END"
|
||||
assert result["messageId"] == "assistant-run-1"
|
||||
assert isinstance(result.get("workerAgentOutput"), dict)
|
||||
assert "stage" not in result
|
||||
assert "model" not in result
|
||||
assert result["status"] == "success"
|
||||
assert result["answer"] == "done"
|
||||
assert result["key_points"] == ["point1"]
|
||||
assert result["result_type"] == "execution_report"
|
||||
assert result["suggested_actions"] == ["action1"]
|
||||
assert result["ui_schema"] == {"version": "2.0"}
|
||||
assert "inputTokens" not in result
|
||||
assert "outputTokens" not in result
|
||||
assert "cost" not in result
|
||||
assert "latencyMs" not in result
|
||||
assert "model" not in result
|
||||
|
||||
|
||||
def test_text_message_end_agui_event_strips_internal_usage_fields() -> None:
|
||||
event = {
|
||||
"type": "TEXT_MESSAGE_END",
|
||||
"threadId": "thread-1",
|
||||
"runId": "run-1",
|
||||
"messageId": "assistant-run-1",
|
||||
"role": "assistant",
|
||||
"stage": "worker",
|
||||
"status": "success",
|
||||
"answer": "done",
|
||||
"key_points": [],
|
||||
"result_type": "execution_report",
|
||||
"suggested_actions": [],
|
||||
"inputTokens": 100,
|
||||
"outputTokens": 50,
|
||||
"cost": 0.01,
|
||||
"latencyMs": 1000,
|
||||
"model": "deepseek-chat",
|
||||
}
|
||||
|
||||
result = to_agui_wire_event(event)
|
||||
|
||||
assert result["type"] == "TEXT_MESSAGE_END"
|
||||
assert result["messageId"] == "assistant-run-1"
|
||||
assert "inputTokens" not in result
|
||||
assert "outputTokens" not in result
|
||||
assert "cost" not in result
|
||||
assert "latencyMs" not in result
|
||||
assert "model" not in result
|
||||
|
||||
|
||||
def test_tool_call_result_agui_event_compiles_ui_hints_to_ui_schema() -> None:
|
||||
event = {
|
||||
"type": "TOOL_CALL_RESULT",
|
||||
"threadId": "thread-1",
|
||||
"runId": "run-1",
|
||||
"messageId": "tool-1",
|
||||
"role": "tool",
|
||||
"stage": "worker",
|
||||
"tool_name": "calendar_read",
|
||||
"tool_call_id": "call-1",
|
||||
"tool_call_args": {"page": 1},
|
||||
"status": "success",
|
||||
"result_summary": "ok",
|
||||
"ui_hints": {
|
||||
"intent": "status",
|
||||
"status": "success",
|
||||
"title": "Done",
|
||||
},
|
||||
}
|
||||
|
||||
result = to_agui_wire_event(event)
|
||||
|
||||
assert result["type"] == "TOOL_CALL_RESULT"
|
||||
assert "ui_hints" not in result
|
||||
assert isinstance(result.get("ui_schema"), dict)
|
||||
|
||||
|
||||
def test_text_message_end_agui_event_compiles_ui_hints_to_ui_schema() -> None:
|
||||
event = {
|
||||
"type": "TEXT_MESSAGE_END",
|
||||
"threadId": "thread-1",
|
||||
"runId": "run-1",
|
||||
"messageId": "assistant-1",
|
||||
"role": "assistant",
|
||||
"stage": "worker",
|
||||
"status": "success",
|
||||
"answer": "done",
|
||||
"key_points": [],
|
||||
"result_type": "summary",
|
||||
"suggested_actions": [],
|
||||
"ui_hints": {
|
||||
"intent": "message",
|
||||
"status": "info",
|
||||
"body": "done",
|
||||
},
|
||||
}
|
||||
|
||||
result = to_agui_wire_event(event)
|
||||
|
||||
assert result["type"] == "TEXT_MESSAGE_END"
|
||||
assert "ui_hints" not in result
|
||||
assert isinstance(result.get("ui_schema"), dict)
|
||||
|
||||
|
||||
def test_step_started_internal_event_keeps_step_name() -> None:
|
||||
internal = {
|
||||
"type": "step.start",
|
||||
"threadId": "thread-1",
|
||||
"runId": "run-1",
|
||||
"stepName": "worker",
|
||||
}
|
||||
|
||||
result = to_agui_wire_event(internal)
|
||||
|
||||
assert result["type"] == "STEP_STARTED"
|
||||
assert result["stepName"] == "worker"
|
||||
|
||||
@@ -28,27 +28,6 @@ class _FakeSessionCtx:
|
||||
del exc_type, exc, tb
|
||||
|
||||
|
||||
class _FakeToolResultStorage:
|
||||
def __init__(self) -> None:
|
||||
self.upload_calls: list[dict[str, object]] = []
|
||||
|
||||
async def upload_json(
|
||||
self,
|
||||
*,
|
||||
bucket: str,
|
||||
path: str,
|
||||
payload: dict[str, object],
|
||||
) -> str:
|
||||
self.upload_calls.append(
|
||||
{
|
||||
"bucket": bucket,
|
||||
"path": path,
|
||||
"payload": payload,
|
||||
}
|
||||
)
|
||||
return path
|
||||
|
||||
|
||||
def _patch_repositories(
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
captured: dict[str, object],
|
||||
@@ -90,25 +69,6 @@ async def test_store_persists_worker_output_with_answer_as_content(
|
||||
_patch_repositories(monkeypatch, captured, fake_chat_session)
|
||||
store = store_module.SqlAlchemyEventStore(session_factory=lambda: _FakeSessionCtx())
|
||||
|
||||
await store.persist(
|
||||
{
|
||||
"type": "TEXT_MESSAGE_START",
|
||||
"threadId": "00000000-0000-0000-0000-000000000001",
|
||||
"runId": "run-1",
|
||||
"messageId": "assistant-run-1",
|
||||
"role": "assistant",
|
||||
"stage": "worker",
|
||||
}
|
||||
)
|
||||
await store.persist(
|
||||
{
|
||||
"type": "TEXT_MESSAGE_CONTENT",
|
||||
"threadId": "00000000-0000-0000-0000-000000000001",
|
||||
"runId": "run-1",
|
||||
"messageId": "assistant-run-1",
|
||||
"delta": "legacy-text",
|
||||
}
|
||||
)
|
||||
await store.persist(
|
||||
{
|
||||
"type": "TEXT_MESSAGE_END",
|
||||
@@ -119,13 +79,18 @@ async def test_store_persists_worker_output_with_answer_as_content(
|
||||
"outputTokens": 5,
|
||||
"cost": "0.123",
|
||||
"latencyMs": 250,
|
||||
"workerAgentOutput": {
|
||||
"role": "assistant",
|
||||
"stage": "worker",
|
||||
"status": "success",
|
||||
"answer": "worker-answer",
|
||||
"key_points": [],
|
||||
"result_type": "summary",
|
||||
"suggested_actions": [],
|
||||
"error": None,
|
||||
"ui_hints": {
|
||||
"intent": "message",
|
||||
"status": "success",
|
||||
"answer": "worker-answer",
|
||||
"key_points": [],
|
||||
"result_type": "summary",
|
||||
"suggested_actions": [],
|
||||
"error": None,
|
||||
"sections": [],
|
||||
},
|
||||
}
|
||||
)
|
||||
@@ -134,7 +99,9 @@ async def test_store_persists_worker_output_with_answer_as_content(
|
||||
assert append_kwargs["seq"] == 7
|
||||
assert append_kwargs["content"] == "worker-answer"
|
||||
metadata = cast(dict[str, Any], append_kwargs["metadata"])
|
||||
assert sorted(metadata.keys()) == ["agent_type", "run_id", "worker_agent_output"]
|
||||
assert metadata["worker_agent_output"]["answer"] == "worker-answer"
|
||||
assert metadata["worker_agent_output"]["ui_hints"]["intent"] == "message"
|
||||
assert append_kwargs["cost"] == Decimal("0.123")
|
||||
assert captured["message_delta"] == 1
|
||||
assert captured["token_delta"] == 8
|
||||
@@ -148,28 +115,21 @@ async def test_store_persists_tool_output_with_summary_as_content(
|
||||
fake_chat_session = SimpleNamespace(state_snapshot={}, message_count=2)
|
||||
_patch_repositories(monkeypatch, captured, fake_chat_session)
|
||||
|
||||
fake_storage = _FakeToolResultStorage()
|
||||
store = store_module.SqlAlchemyEventStore(
|
||||
session_factory=lambda: _FakeSessionCtx(),
|
||||
tool_result_storage=fake_storage,
|
||||
tool_result_bucket="agent-tool-results",
|
||||
)
|
||||
store = store_module.SqlAlchemyEventStore(session_factory=lambda: _FakeSessionCtx())
|
||||
await store.persist(
|
||||
{
|
||||
"type": "TOOL_CALL_RESULT",
|
||||
"threadId": "00000000-0000-0000-0000-000000000001",
|
||||
"runId": "run-1",
|
||||
"toolName": "calendar_write",
|
||||
"taskId": "t1",
|
||||
"stage": "worker",
|
||||
"toolAgentOutput": {
|
||||
"tool_name": "calendar_write",
|
||||
"tool_call_id": "call-1",
|
||||
"tool_call_args": {"title": "A"},
|
||||
"tool_name": "calendar_write",
|
||||
"tool_call_id": "call-1",
|
||||
"tool_call_args": {"title": "A"},
|
||||
"status": "success",
|
||||
"result_summary": "已创建日程 A",
|
||||
"ui_hints": {
|
||||
"intent": "status",
|
||||
"status": "success",
|
||||
"result_summary": "已创建日程 A",
|
||||
"ui_hints": None,
|
||||
"error": None,
|
||||
"sections": [],
|
||||
},
|
||||
}
|
||||
)
|
||||
@@ -178,6 +138,6 @@ async def test_store_persists_tool_output_with_summary_as_content(
|
||||
assert getattr(append_kwargs["role"], "value", None) == "tool"
|
||||
assert append_kwargs["content"] == "已创建日程 A"
|
||||
metadata = cast(dict[str, Any], append_kwargs["metadata"])
|
||||
assert sorted(metadata.keys()) == ["run_id", "tool_agent_output"]
|
||||
assert metadata["tool_agent_output"]["result_summary"] == "已创建日程 A"
|
||||
assert metadata["storage_bucket"] == "agent-tool-results"
|
||||
assert len(fake_storage.upload_calls) == 1
|
||||
assert metadata["tool_agent_output"]["ui_hints"]["intent"] == "status"
|
||||
|
||||
Reference in New Issue
Block a user