mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
Python: Integration tests for Azure AI client and fixes in samples (#2387)
* Added integration tests * Update python/packages/azure-ai/tests/test_azure_ai_client.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Small fixes in samples * Small fix * Small fix --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
Unverified
parent
b7a19b0fa2
commit
ee8936d514
@@ -1,9 +1,16 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
import os
|
||||
from collections.abc import AsyncIterator
|
||||
from contextlib import asynccontextmanager
|
||||
from typing import Annotated
|
||||
from unittest.mock import AsyncMock, MagicMock, patch
|
||||
|
||||
import pytest
|
||||
from agent_framework import (
|
||||
AgentRunResponse,
|
||||
AgentRunResponseUpdate,
|
||||
ChatAgent,
|
||||
ChatClientProtocol,
|
||||
ChatMessage,
|
||||
ChatOptions,
|
||||
@@ -11,15 +18,50 @@ from agent_framework import (
|
||||
TextContent,
|
||||
)
|
||||
from agent_framework.exceptions import ServiceInitializationError
|
||||
from azure.ai.projects.aio import AIProjectClient
|
||||
from azure.ai.projects.models import (
|
||||
ResponseTextFormatConfigurationJsonSchema,
|
||||
)
|
||||
from azure.identity.aio import AzureCliCredential
|
||||
from openai.types.responses.parsed_response import ParsedResponse
|
||||
from openai.types.responses.response import Response as OpenAIResponse
|
||||
from pydantic import BaseModel, ConfigDict, ValidationError
|
||||
from pydantic import BaseModel, ConfigDict, Field, ValidationError
|
||||
|
||||
from agent_framework_azure_ai import AzureAIClient, AzureAISettings
|
||||
|
||||
skip_if_azure_ai_integration_tests_disabled = pytest.mark.skipif(
|
||||
os.getenv("RUN_INTEGRATION_TESTS", "false").lower() != "true"
|
||||
or os.getenv("AZURE_AI_PROJECT_ENDPOINT", "") in ("", "https://test-project.cognitiveservices.azure.com/")
|
||||
or os.getenv("AZURE_AI_MODEL_DEPLOYMENT_NAME", "") == "",
|
||||
reason=(
|
||||
"No real AZURE_AI_PROJECT_ENDPOINT or AZURE_AI_MODEL_DEPLOYMENT_NAME provided; skipping integration tests."
|
||||
if os.getenv("RUN_INTEGRATION_TESTS", "false").lower() == "true"
|
||||
else "Integration tests are disabled."
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@asynccontextmanager
|
||||
async def temporary_chat_client(agent_name: str) -> AsyncIterator[AzureAIClient]:
|
||||
"""Async context manager that creates an Azure AI agent and yields an `AzureAIClient`.
|
||||
|
||||
The underlying agent version is cleaned up automatically after use.
|
||||
Tests can construct their own `ChatAgent` instances from the yielded client.
|
||||
"""
|
||||
endpoint = os.environ["AZURE_AI_PROJECT_ENDPOINT"]
|
||||
async with (
|
||||
AzureCliCredential() as credential,
|
||||
AIProjectClient(endpoint=endpoint, credential=credential) as project_client,
|
||||
):
|
||||
chat_client = AzureAIClient(
|
||||
project_client=project_client,
|
||||
agent_name=agent_name,
|
||||
)
|
||||
try:
|
||||
yield chat_client
|
||||
finally:
|
||||
await project_client.agents.delete(agent_name=agent_name)
|
||||
|
||||
|
||||
def create_test_azure_ai_client(
|
||||
mock_project_client: MagicMock,
|
||||
@@ -751,3 +793,64 @@ def mock_project_client() -> MagicMock:
|
||||
mock_client.close = AsyncMock()
|
||||
|
||||
return mock_client
|
||||
|
||||
|
||||
def get_weather(
|
||||
location: Annotated[str, Field(description="The location to get the weather for.")],
|
||||
) -> str:
|
||||
"""Get the weather for a given location."""
|
||||
return f"The weather in {location} is sunny with a high of 25°C."
|
||||
|
||||
|
||||
@pytest.mark.flaky
|
||||
@skip_if_azure_ai_integration_tests_disabled
|
||||
async def test_azure_ai_chat_client_agent_basic_run() -> None:
|
||||
"""Test ChatAgent basic run functionality with AzureAIClient."""
|
||||
async with (
|
||||
temporary_chat_client(agent_name="BasicRunAgent") as chat_client,
|
||||
ChatAgent(chat_client=chat_client) as agent,
|
||||
):
|
||||
response = await agent.run("Hello! Please respond with 'Hello World' exactly.")
|
||||
|
||||
# Validate response
|
||||
assert isinstance(response, AgentRunResponse)
|
||||
assert response.text is not None
|
||||
assert len(response.text) > 0
|
||||
assert "Hello World" in response.text
|
||||
|
||||
|
||||
@pytest.mark.flaky
|
||||
@skip_if_azure_ai_integration_tests_disabled
|
||||
async def test_azure_ai_chat_client_agent_basic_run_streaming() -> None:
|
||||
"""Test ChatAgent basic streaming functionality with AzureAIClient."""
|
||||
async with (
|
||||
temporary_chat_client(agent_name="BasicRunStreamingAgent") as chat_client,
|
||||
ChatAgent(chat_client=chat_client) as agent,
|
||||
):
|
||||
full_message: str = ""
|
||||
async for chunk in agent.run_stream("Please respond with exactly: 'This is a streaming response test.'"):
|
||||
assert chunk is not None
|
||||
assert isinstance(chunk, AgentRunResponseUpdate)
|
||||
if chunk.text:
|
||||
full_message += chunk.text
|
||||
|
||||
# Validate streaming response
|
||||
assert len(full_message) > 0
|
||||
assert "streaming response test" in full_message.lower()
|
||||
|
||||
|
||||
@pytest.mark.flaky
|
||||
@skip_if_azure_ai_integration_tests_disabled
|
||||
async def test_azure_ai_chat_client_agent_with_tools() -> None:
|
||||
"""Test ChatAgent tools with AzureAIClient."""
|
||||
async with (
|
||||
temporary_chat_client(agent_name="RunToolsAgent") as chat_client,
|
||||
ChatAgent(chat_client=chat_client, tools=[get_weather]) as agent,
|
||||
):
|
||||
response = await agent.run("What's the weather like in Seattle?")
|
||||
|
||||
# Validate response
|
||||
assert isinstance(response, AgentRunResponse)
|
||||
assert response.text is not None
|
||||
assert len(response.text) > 0
|
||||
assert any(word in response.text.lower() for word in ["sunny", "25"])
|
||||
|
||||
Reference in New Issue
Block a user