mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
c8694a8c76
* Workflow init commit * Add samples and clean up * ExecutionContext -> WorkflowContext * Address comments 1 * Fix mypy * flatting folder structure, and rename contexts * Remove add_loop * Add map reduce sample, remove Activation conditions * Add AgentExecutor and allow multiple handlers per executor * Minor improvement * Add RequestInfoExecutor * Add unit tests part 1 * Address comments 2 * Pre-commit update * Add run method and more unit tests * Add xml docs * run_stream -> run_streaming * message_handler -> handler --------- Co-authored-by: Chris <66376200+crickman@users.noreply.github.com> Co-authored-by: Evan Mattson <evan.mattson@microsoft.com>
103 lines
4.0 KiB
Python
103 lines
4.0 KiB
Python
# Copyright (c) Microsoft. All rights reserved.
|
|
|
|
import pytest
|
|
from agent_framework.workflow import Executor, WorkflowContext, handler
|
|
|
|
|
|
def test_executor_without_handlers():
|
|
"""Test that an executor without handlers raises an error when trying to run."""
|
|
|
|
class MockExecutorWithoutHandlers(Executor):
|
|
"""A mock executor that does not implement any handlers."""
|
|
|
|
pass
|
|
|
|
with pytest.raises(ValueError):
|
|
MockExecutorWithoutHandlers()
|
|
|
|
|
|
def test_executor_handler_without_annotations():
|
|
"""Test that an executor with one handler without annotations raises an error when trying to run."""
|
|
|
|
with pytest.raises(ValueError):
|
|
|
|
class MockExecutorWithOneHandlerWithoutAnnotations(Executor): # type: ignore
|
|
"""A mock executor with one handler that does not implement any annotations."""
|
|
|
|
@handler
|
|
async def handle(self, message, ctx) -> None: # type: ignore
|
|
"""A mock handler that does not implement any annotations."""
|
|
pass
|
|
|
|
|
|
def test_executor_invalid_handler_signature():
|
|
"""Test that an executor with an invalid handler signature raises an error when trying to run."""
|
|
|
|
with pytest.raises(ValueError):
|
|
|
|
class MockExecutorWithInvalidHandlerSignature(Executor): # type: ignore
|
|
"""A mock executor with an invalid handler signature."""
|
|
|
|
@handler # type: ignore
|
|
async def handle(self, message, other, ctx) -> None: # type: ignore
|
|
"""A mock handler with an invalid signature."""
|
|
pass
|
|
|
|
|
|
def test_executor_with_valid_handlers():
|
|
"""Test that an executor with valid handlers can be instantiated and run."""
|
|
|
|
class MockExecutorWithValidHandlers(Executor): # type: ignore
|
|
"""A mock executor with valid handlers."""
|
|
|
|
@handler
|
|
async def handle_text(self, text: str, ctx: WorkflowContext) -> None: # type: ignore
|
|
"""A mock handler with a valid signature."""
|
|
pass
|
|
|
|
@handler
|
|
async def handle_number(self, number: int, ctx: WorkflowContext) -> None: # type: ignore
|
|
"""Another mock handler with a valid signature."""
|
|
pass
|
|
|
|
executor = MockExecutorWithValidHandlers()
|
|
assert executor.id is not None
|
|
assert len(executor._handlers) == 2 # type: ignore
|
|
assert executor.can_handle("text") is True
|
|
assert executor.can_handle(42) is True
|
|
assert executor.can_handle(3.14) is False
|
|
|
|
|
|
def test_executor_handlers_with_output_types():
|
|
"""Test that an executor with handlers that specify output types can be instantiated and run."""
|
|
|
|
class MockExecutorWithOutputTypes(Executor): # type: ignore
|
|
"""A mock executor with handlers that specify output types."""
|
|
|
|
@handler(output_types=[str])
|
|
async def handle_string(self, text: str, ctx: WorkflowContext) -> None: # type: ignore
|
|
"""A mock handler that outputs a string."""
|
|
pass
|
|
|
|
@handler(output_types=[int])
|
|
async def handle_integer(self, number: int, ctx: WorkflowContext) -> None: # type: ignore
|
|
"""A mock handler that outputs an integer."""
|
|
pass
|
|
|
|
executor = MockExecutorWithOutputTypes()
|
|
assert len(executor._handlers) == 2 # type: ignore
|
|
|
|
string_handler = executor._handlers[str] # type: ignore
|
|
assert string_handler is not None
|
|
assert string_handler._handler_spec is not None # type: ignore
|
|
assert string_handler._handler_spec["name"] == "handle_string" # type: ignore
|
|
assert string_handler._handler_spec["message_type"] is str # type: ignore
|
|
assert string_handler._handler_spec["output_types"] == [str] # type: ignore
|
|
|
|
int_handler = executor._handlers[int] # type: ignore
|
|
assert int_handler is not None
|
|
assert int_handler._handler_spec is not None # type: ignore
|
|
assert int_handler._handler_spec["name"] == "handle_integer" # type: ignore
|
|
assert int_handler._handler_spec["message_type"] is int # type: ignore
|
|
assert int_handler._handler_spec["output_types"] == [int] # type: ignore
|