-
Notifications
You must be signed in to change notification settings - Fork 56
Integration Testing Framework #228
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
59 commits
Select commit
Hold shift + click to select a range
cfb8847
basic integration utility
rodrigobr-msft 4d93a46
Integration test suite factory implementation
rodrigobr-msft be2fb1c
Implementing core models for integration testing
rodrigobr-msft 0d5539a
AutoClient mockup
rodrigobr-msft bf4c006
Adding runner starter code
rodrigobr-msft ebe622d
Adding foundational classes
rodrigobr-msft 45678e9
Drafting AgentClient and ResponseClient implementations
rodrigobr-msft c2b84cb
Spec test
rodrigobr-msft 2816e68
Filling in more implementation details
rodrigobr-msft 2214827
More files
rodrigobr-msft c90c8e4
Cleaning up implementations
rodrigobr-msft 36f5c3b
Adding expect replies sending method
rodrigobr-msft dfdd959
Beginning unit tests
rodrigobr-msft d4828fb
Adding integration decor from sample test cases
rodrigobr-msft 91b3c44
Integration from service url tests
rodrigobr-msft 1eefe44
_handle_conversation implementation for response_client
rodrigobr-msft a06da9a
AgentClient tests completed
rodrigobr-msft d36ec7a
Creating response client tests
rodrigobr-msft c096048
Hosting server for response client
rodrigobr-msft 5451ddf
Response client tests completed
rodrigobr-msft c2cdd40
Beginning refactor of aiohttp runner
rodrigobr-msft 7d91ef9
Unit test updates
rodrigobr-msft 87610a5
Fixing issues in refactor
rodrigobr-msft ddfdd0b
Fixed TestIntegrationFromSample unit test
rodrigobr-msft dd0a87d
Another commit
rodrigobr-msft 6a4e8ef
Reorganizing files
rodrigobr-msft 7793790
Completed TestIntegrationFromServiceUrl unit tests
rodrigobr-msft 3ebbd44
Reformatting with black
rodrigobr-msft a6681bf
Quickstart integration test beginning
rodrigobr-msft 1a7264b
Draft of quickstart sample setup
rodrigobr-msft 9ba4a43
Environment config connection
rodrigobr-msft fab4368
Renaming messaging endpoint to agent url
rodrigobr-msft a111155
Removing unnecessary files
rodrigobr-msft a2a1092
Fixing agent client payload sending
rodrigobr-msft ae8a286
First successful integration test
rodrigobr-msft 9a5a6a8
Beginning foundational test cases
rodrigobr-msft aad011a
TypingIndicator test
rodrigobr-msft be0032a
Adding more test cases
rodrigobr-msft e3f4324
More foundational integration test cases
rodrigobr-msft a077eed
Reorganizing testing tools into package
rodrigobr-msft 49161c3
Polished the testing framework package
rodrigobr-msft 69d68d4
Adding verbose logging for results with benchmark tool
rodrigobr-msft 3dc3efa
General cleanup
rodrigobr-msft 054a3a2
Adding README
rodrigobr-msft 8a5f22e
Revising README
rodrigobr-msft 4b7c673
Formatting
rodrigobr-msft 01f8f5a
Addressing PR comments
rodrigobr-msft 9cccc1f
Merge branch 'main' of https://github.com/microsoft/Agents-for-python…
rodrigobr-msft 8f87aff
Removing unused import
rodrigobr-msft e742e00
Update dev/microsoft-agents-testing/microsoft_agents/testing/sdk_conf…
rodrigobr-msft a6e305a
Update dev/microsoft-agents-testing/pyproject.toml
rodrigobr-msft c3877a3
Update dev/microsoft-agents-testing/microsoft_agents/testing/auth/gen…
rodrigobr-msft fb5b76d
Update dev/microsoft-agents-testing/microsoft_agents/testing/integrat…
rodrigobr-msft 5eb9bfb
Removing unused code
rodrigobr-msft 81b5d6b
Merge branch 'users/robrandao/integration' of https://github.com/micr…
rodrigobr-msft 242d6e1
Writing draft README for testing package
rodrigobr-msft 9fc4dc1
Second pass for README.md
rodrigobr-msft d0e1e13
Removing link to PyPI
rodrigobr-msft b969083
Merge branch 'main' into users/robrandao/integration
rodrigobr-msft File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,25 @@ | ||
| This directory contains tools to aid the developers of the Microsoft 365 Agents SDK for Python. | ||
| # Development Tools | ||
|
|
||
| ### `benchmark` | ||
| Development utilities for the Microsoft Agents for Python project. | ||
|
|
||
| This folder contains benchmarking utilities built in Python to send concurrent requests | ||
| to an agent. | ||
| ## Contents | ||
|
|
||
| - **[`install.sh`](install.sh)** - Installs testing framework in editable mode | ||
| - **[`benchmark/`](benchmark/)** - Performance testing and stress testing tools | ||
| - **[`microsoft-agents-testing/`](microsoft-agents-testing/)** - Testing framework package | ||
|
|
||
| ## Quick Setup | ||
|
|
||
| ```bash | ||
| ./install.sh | ||
| ``` | ||
|
|
||
| ## Benchmarking | ||
|
|
||
| Performance testing tools with support for concurrent workers and authentication. Requires a running agent instance and Azure Bot Service credentials. | ||
|
|
||
| See [benchmark/README.md](benchmark/README.md) for setup and usage details. | ||
|
|
||
| ## Testing Framework | ||
|
|
||
| Provides testing utilities and helpers for Microsoft Agents development. Installed in editable mode for active development. |
Empty file.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| from .executor import ExecutionResult | ||
|
|
||
|
|
||
| def output_results(results: list[ExecutionResult]) -> None: | ||
| """Output the results of the benchmark to the console.""" | ||
|
|
||
| for result in results: | ||
| status = "Success" if result.success else "Failure" | ||
| print( | ||
| f"Execution ID: {result.exe_id}, Duration: {result.duration:.4f} seconds, Status: {status}" | ||
| ) | ||
| print(result.result) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| pip install -e ./microsoft-agents-testing/ --config-settings editable_mode=compat |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,171 @@ | ||
| # Microsoft 365 Agents SDK for Python - Testing Framework | ||
|
|
||
| A comprehensive testing framework designed specifically for Microsoft 365 Agents SDK, providing essential utilities and abstractions to streamline integration testing, authentication, and end-to-end agent validation. | ||
|
|
||
| ## Why This Package Exists | ||
|
|
||
| Building and testing conversational agents presents unique challenges that standard testing frameworks don't address. This package eliminates these pain points by providing useful abstractions specifically designed for agent testing scenarios. | ||
|
|
||
| ## Key Features | ||
|
|
||
| ### 🔐 Authentication Utilities | ||
| - **OAuth2 Token Generation**: Generate access tokens using client credentials flow | ||
| - **Configuration-Based Auth**: Load credentials from environment variables or config objects | ||
| - **MSAL Integration**: Built-in support for Microsoft Authentication Library | ||
|
|
||
| ```python | ||
| from microsoft_agents.testing import generate_token, generate_token_from_config | ||
|
|
||
| # Generate token directly | ||
| token = generate_token( | ||
| app_id="your-app-id", | ||
| app_secret="your-secret", | ||
| tenant_id="your-tenant" | ||
| ) | ||
|
|
||
| # Or from SDK config | ||
| token = generate_token_from_config(sdk_config) | ||
| ``` | ||
|
|
||
| ### 🧪 Integration Test Framework | ||
| - **Pytest Fixtures**: Pre-built fixtures for common test scenarios | ||
| - **Environment Abstraction**: Reusable environment setup for different hosting configurations | ||
| - **Sample Management**: Base classes for organizing test samples and configurations | ||
| - **Application Runners**: Abstract server lifecycle management for integration tests | ||
|
|
||
| ```python | ||
| from microsoft_agents.testing import Integration, Environment, Sample | ||
|
|
||
| class MyAgentTests(Integration): | ||
| _sample_cls = MyAgentSample | ||
| _environment_cls = AiohttpEnvironment | ||
|
|
||
| @pytest.mark.asyncio | ||
| async def test_conversation_flow(self, agent_client, sample): | ||
| # Client and sample are automatically set up via fixtures | ||
| response = await agent_client.send_activity("Hello") | ||
| assert response is not None | ||
| ``` | ||
|
|
||
| ### 🤖 Agent Communication Clients | ||
| - **AgentClient**: High-level client for sending Activities to agents | ||
| - **ResponseClient**: Handle responses from agent services | ||
| - **Automatic Token Management**: Clients handle authentication automatically | ||
| - **Delivery Mode Support**: Test both standard and `ExpectReplies` delivery patterns | ||
|
|
||
| ```python | ||
| from microsoft_agents.testing import AgentClient | ||
|
|
||
| client = AgentClient( | ||
| agent_url="http://localhost:3978", | ||
| cid="conversation-id", | ||
| client_id="your-client-id", | ||
| tenant_id="your-tenant-id", | ||
| client_secret="your-secret" | ||
| ) | ||
|
|
||
| # Send simple text message | ||
| response = await client.send_activity("What's the weather?") | ||
|
|
||
| # Send Activity with ExpectReplies | ||
| replies = await client.send_expect_replies( | ||
| Activity(type=ActivityTypes.message, text="Hello") | ||
| ) | ||
| ``` | ||
|
|
||
| ### 🛠️ Testing Utilities | ||
| - **Activity Population**: Automatically fill default Activity properties for testing | ||
| - **URL Parsing**: Extract host and port from service URLs | ||
| - **Configuration Management**: Centralized SDK configuration for tests | ||
|
|
||
| ```python | ||
| from microsoft_agents.testing import populate_activity, get_host_and_port | ||
|
|
||
| # Populate test activity with defaults | ||
| activity = populate_activity( | ||
| Activity(text="Hello"), | ||
| defaults={"service_url": "http://localhost", "channel_id": "test"} | ||
| ) | ||
|
|
||
| # Parse service URLs | ||
| host, port = get_host_and_port("http://localhost:3978/api/messages") | ||
| ``` | ||
|
|
||
| ## Who Should Use This Package | ||
|
|
||
| - **Agent Developers**: Testing agents built with `microsoft-agents-hosting-core` and related packages | ||
| - **QA Engineers**: Writing integration and E2E tests for conversational AI systems | ||
| - **DevOps Teams**: Automating agent validation in CI/CD pipelines | ||
| - **Sample Authors**: Creating reproducible examples and documentation | ||
|
|
||
| ## Integration with CI/CD | ||
|
|
||
| This package is designed for seamless integration into continuous integration pipelines: | ||
|
|
||
| ```yaml | ||
| # Example: GitHub Actions | ||
| - name: Run Agent Integration Tests | ||
| run: | | ||
| pip install microsoft-agents-testing pytest pytest-asyncio | ||
| pytest tests/integration/ -v | ||
| env: | ||
| CLIENT_ID: ${{ secrets.AGENT_CLIENT_ID }} | ||
| CLIENT_SECRET: ${{ secrets.AGENT_CLIENT_SECRET }} | ||
| TENANT_ID: ${{ secrets.TENANT_ID }} | ||
| ``` | ||
|
|
||
| ## Quick Start Example | ||
|
|
||
| ```python | ||
| import pytest | ||
| from microsoft_agents.testing import Integration, AiohttpEnvironment, Sample | ||
| from microsoft_agents.activity import Activity | ||
|
|
||
| class MyAgentSample(Sample): | ||
| async def init_app(self): | ||
| # Initialize your agent application | ||
| self.app = create_my_agent_app(self.env) | ||
|
|
||
| @classmethod | ||
| async def get_config(cls): | ||
| return {"service_url": "http://localhost:3978"} | ||
|
|
||
| class TestMyAgent(Integration): | ||
| _sample_cls = MyAgentSample | ||
| _environment_cls = AiohttpEnvironment | ||
|
|
||
| _agent_url = "http://localhost:3978" | ||
| _cid = "test-conversation" | ||
|
|
||
| @pytest.mark.asyncio | ||
| async def test_greeting(self, agent_client): | ||
| response = await agent_client.send_activity("Hello") | ||
| assert "Hi there" in response | ||
|
|
||
| @pytest.mark.asyncio | ||
| async def test_conversation(self, agent_client): | ||
| replies = await agent_client.send_expect_replies("What can you do?") | ||
| assert len(replies) > 0 | ||
| assert replies[0].type == "message" | ||
| ``` | ||
|
|
||
| ## Related Packages | ||
|
|
||
| This package complements the Microsoft 365 Agents SDK ecosystem: | ||
|
|
||
| - `microsoft-agents-activity`: Activity types and protocols | ||
| - `microsoft-agents-hosting-core`: Core hosting framework | ||
| - `microsoft-agents-hosting-aiohttp`: aiohttp hosting integration | ||
| - `microsoft-agents-authentication-msal`: MSAL authentication | ||
|
|
||
| ## Contributing | ||
|
|
||
| This project welcomes contributions and suggestions. Most contributions require you to agree to a Contributor License Agreement (CLA). For details, visit [https://cla.opensource.microsoft.com](https://cla.opensource.microsoft.com). | ||
|
|
||
| ## License | ||
|
|
||
| MIT | ||
|
|
||
| ## Support | ||
|
|
||
| For issues, questions, or contributions, please visit the [GitHub repository](https://github.com/microsoft/Agents-for-python). |
30 changes: 30 additions & 0 deletions
30
dev/microsoft-agents-testing/microsoft_agents/testing/__init__.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| from .sdk_config import SDKConfig | ||
|
|
||
| from .auth import generate_token, generate_token_from_config | ||
|
|
||
| from .utils import populate_activity, get_host_and_port | ||
|
|
||
| from .integration import ( | ||
| Sample, | ||
| Environment, | ||
| ApplicationRunner, | ||
| AgentClient, | ||
| ResponseClient, | ||
| AiohttpEnvironment, | ||
| Integration, | ||
| ) | ||
|
|
||
| __all__ = [ | ||
| "SDKConfig", | ||
| "generate_token", | ||
| "generate_token_from_config", | ||
| "Sample", | ||
| "Environment", | ||
| "ApplicationRunner", | ||
| "AgentClient", | ||
| "ResponseClient", | ||
| "AiohttpEnvironment", | ||
| "Integration", | ||
| "populate_activity", | ||
| "get_host_and_port", | ||
| ] |
3 changes: 3 additions & 0 deletions
3
dev/microsoft-agents-testing/microsoft_agents/testing/auth/__init__.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| from .generate_token import generate_token, generate_token_from_config | ||
|
|
||
| __all__ = ["generate_token", "generate_token_from_config"] |
51 changes: 51 additions & 0 deletions
51
dev/microsoft-agents-testing/microsoft_agents/testing/auth/generate_token.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,51 @@ | ||
| import requests | ||
|
|
||
| from microsoft_agents.hosting.core import AgentAuthConfiguration | ||
| from microsoft_agents.testing.sdk_config import SDKConfig | ||
|
|
||
|
|
||
| def generate_token(app_id: str, app_secret: str, tenant_id: str) -> str: | ||
| """Generate a token using the provided app credentials. | ||
|
|
||
| :param app_id: Application (client) ID. | ||
| :param app_secret: Application client secret. | ||
| :param tenant_id: Directory (tenant) ID. | ||
| :return: Generated access token as a string. | ||
| """ | ||
|
|
||
| authority_endpoint = ( | ||
| f"https://login.microsoftonline.com/{tenant_id}/oauth2/v2.0/token" | ||
| ) | ||
|
|
||
| res = requests.post( | ||
| authority_endpoint, | ||
| headers={ | ||
| "Content-Type": "application/x-www-form-urlencoded", | ||
| }, | ||
| data={ | ||
| "grant_type": "client_credentials", | ||
| "client_id": app_id, | ||
| "client_secret": app_secret, | ||
| "scope": f"{app_id}/.default", | ||
| }, | ||
| timeout=10, | ||
| ) | ||
| return res.json().get("access_token") | ||
|
|
||
|
|
||
| def generate_token_from_config(sdk_config: SDKConfig) -> str: | ||
| """Generates a token using a provided config object. | ||
|
|
||
| :param sdk_config: Configuration dictionary containing connection settings. | ||
rodrigobr-msft marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| :return: Generated access token as a string. | ||
| """ | ||
|
|
||
| settings: AgentAuthConfiguration = sdk_config.get_connection() | ||
|
|
||
| app_id = settings.CLIENT_ID | ||
| app_secret = settings.CLIENT_SECRET | ||
| tenant_id = settings.TENANT_ID | ||
|
|
||
| if not app_id or not app_secret or not tenant_id: | ||
| raise ValueError("Incorrect configuration provided for token generation.") | ||
| return generate_token(app_id, app_secret, tenant_id) | ||
19 changes: 19 additions & 0 deletions
19
dev/microsoft-agents-testing/microsoft_agents/testing/integration/__init__.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| from .core import ( | ||
| AgentClient, | ||
| ApplicationRunner, | ||
| AiohttpEnvironment, | ||
| ResponseClient, | ||
| Environment, | ||
| Integration, | ||
| Sample, | ||
| ) | ||
|
|
||
| __all__ = [ | ||
| "AgentClient", | ||
| "ApplicationRunner", | ||
| "AiohttpEnvironment", | ||
| "ResponseClient", | ||
| "Environment", | ||
| "Integration", | ||
| "Sample", | ||
| ] |
20 changes: 20 additions & 0 deletions
20
dev/microsoft-agents-testing/microsoft_agents/testing/integration/core/__init__.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| from .application_runner import ApplicationRunner | ||
| from .aiohttp import AiohttpEnvironment | ||
| from .client import ( | ||
| AgentClient, | ||
| ResponseClient, | ||
| ) | ||
| from .environment import Environment | ||
| from .integration import Integration | ||
| from .sample import Sample | ||
|
|
||
|
|
||
| __all__ = [ | ||
| "AgentClient", | ||
| "ApplicationRunner", | ||
| "AiohttpEnvironment", | ||
| "ResponseClient", | ||
| "Environment", | ||
| "Integration", | ||
| "Sample", | ||
| ] |
4 changes: 4 additions & 0 deletions
4
dev/microsoft-agents-testing/microsoft_agents/testing/integration/core/aiohttp/__init__.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| from .aiohttp_environment import AiohttpEnvironment | ||
| from .aiohttp_runner import AiohttpRunner | ||
|
|
||
| __all__ = ["AiohttpEnvironment", "AiohttpRunner"] |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.