-
Notifications
You must be signed in to change notification settings - Fork 86
Testing initialization helper #416
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
10 commits
Select commit
Hold shift + click to select a range
1091999
agt init foundations
rodrigobr-msft a1fdf11
SourceScenario improvements
rodrigobr-msft 992238f
Adding extra post init information messages
rodrigobr-msft 31bbd80
Fixing tests
rodrigobr-msft 461158a
Merge branch 'main' into users/robrandao/testing-init
rodrigobr-msft 6ca0962
Potential fix for pull request finding
rodrigobr-msft 8c46274
Potential fix for pull request finding
rodrigobr-msft c5d6272
Potential fix for pull request finding
rodrigobr-msft c691fc5
Potential fix for pull request finding
rodrigobr-msft 590da54
Potential fix for pull request finding
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
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
110 changes: 110 additions & 0 deletions
110
dev/testing/microsoft-agents-testing/microsoft_agents/testing/cli/commands/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,110 @@ | ||
| # Copyright (c) Microsoft Corporation. All rights reserved. | ||
| # Licensed under the MIT License. | ||
|
|
||
| """Init CLI command — scaffold a test harness from a preset template.""" | ||
|
|
||
| import shutil | ||
| from pathlib import Path | ||
| from importlib.resources import files as _pkg_files | ||
|
|
||
| import click | ||
|
|
||
| from microsoft_agents.testing.cli.core import pass_output, Output | ||
|
|
||
| # --------------------------------------------------------------------------- | ||
| # Preset discovery — runs once at import time | ||
| # --------------------------------------------------------------------------- | ||
| _PRESETS_ROOT = _pkg_files("microsoft_agents.testing") / "presets" | ||
|
|
||
|
|
||
| def _discover_presets() -> dict: | ||
| try: | ||
| return { | ||
| entry.name: entry | ||
| for entry in _PRESETS_ROOT.iterdir() | ||
| if entry.is_dir() | ||
| } | ||
| except (FileNotFoundError, NotADirectoryError): | ||
| return {} | ||
|
|
||
|
|
||
| PRESETS: dict = _discover_presets() | ||
|
|
||
|
|
||
| # --------------------------------------------------------------------------- | ||
| # Helpers | ||
| # --------------------------------------------------------------------------- | ||
| def _copy_traversable(src, dest: Path) -> None: | ||
| """Recursively copy a Traversable tree into an existing dest directory.""" | ||
| for item in src.iterdir(): | ||
| target = dest / item.name | ||
| if item.is_dir(): | ||
| target.mkdir(parents=True, exist_ok=True) | ||
| _copy_traversable(item, target) | ||
| else: | ||
| target.write_bytes(item.read_bytes()) | ||
|
|
||
|
|
||
| # --------------------------------------------------------------------------- | ||
| # Command | ||
| # --------------------------------------------------------------------------- | ||
| @click.command(name="init") | ||
| @click.argument("preset", required=False, default=None) | ||
| @click.option("--force", is_flag=True, default=False, help="Overwrite any existing files from the preset.") | ||
| @pass_output | ||
| def init_group(out: Output, preset: str, force: bool) -> None: | ||
| """Scaffold a test harness from a preset template. | ||
|
|
||
| PRESET is the name of the harness template to use. | ||
| Omit PRESET to list available presets. | ||
| """ | ||
| if not preset: | ||
| if not PRESETS: | ||
| out.warning("No presets found.") | ||
| else: | ||
| out.info("Available presets:") | ||
| for name in PRESETS: | ||
| out.info(f"\t{name}") | ||
| return | ||
|
|
||
| if preset not in PRESETS: | ||
| available = ", ".join(PRESETS) or "none" | ||
| out.error(f"Unknown preset '{preset}'. Available: {available}") | ||
| raise SystemExit(1) | ||
|
|
||
| cwd = Path.cwd() | ||
| preset_traversable = PRESETS[preset] | ||
|
|
||
| conflicts = [ | ||
| cwd / item.name | ||
| for item in preset_traversable.iterdir() | ||
| if (cwd / item.name).exists() | ||
| ] | ||
|
|
||
| if conflicts and not force: | ||
| names = ", ".join(p.name for p in conflicts) | ||
| out.error(f"Already exists: {names}. Use --force to overwrite.") | ||
| raise SystemExit(1) | ||
|
|
||
| if force: | ||
| for conflict in conflicts: | ||
| if conflict.is_dir(): | ||
| shutil.rmtree(conflict) | ||
| else: | ||
| conflict.unlink() | ||
|
|
||
| out.info(f"Initializing preset '{preset}' ...") | ||
| _copy_traversable(preset_traversable, cwd) | ||
| out.success(f"Done. Files written to {cwd}") | ||
|
|
||
| out.info("") | ||
| out.info("Next step: create .env files for each component from their env.TEMPLATE:") | ||
| env_templates = [ | ||
| cwd / item.name / "env.TEMPLATE" | ||
| for item in preset_traversable.iterdir() | ||
| if item.is_dir() and (cwd / item.name / "env.TEMPLATE").exists() | ||
| ] | ||
| for template in env_templates: | ||
| out.info(f"\t{template.parent.name}/env.TEMPLATE → {template.parent.name}/.env") | ||
| out.info("") | ||
| out.info("Populate each .env with your app credentials and configuration before running.") |
1 change: 0 additions & 1 deletion
1
...oft_agents/testing/cross_sdk/constants.py → ...ing/microsoft_agents/testing/constants.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 |
|---|---|---|
| @@ -1,5 +1,4 @@ | ||
| # Copyright (c) Microsoft Corporation. All rights reserved. | ||
| # Licensed under the MIT License. | ||
|
|
||
| ENTRY_POINT_NAME = "run_agent.ps1" | ||
| DEFAULT_LOCAL_AGENT_ENDPOINT = "http://localhost:3978/api/messages" |
16 changes: 0 additions & 16 deletions
16
dev/testing/microsoft-agents-testing/microsoft_agents/testing/cross_sdk/__init__.py
This file was deleted.
Oops, something went wrong.
10 changes: 0 additions & 10 deletions
10
dev/testing/microsoft-agents-testing/microsoft_agents/testing/cross_sdk/types.py
This file was deleted.
Oops, something went wrong.
27 changes: 0 additions & 27 deletions
27
dev/testing/microsoft-agents-testing/microsoft_agents/testing/cross_sdk/utils.py
This file was deleted.
Oops, something went wrong.
9 changes: 9 additions & 0 deletions
9
...ing/microsoft-agents-testing/microsoft_agents/testing/presets/basic/e2e-tests/config.json
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,9 @@ | ||
| { | ||
| "agents": { | ||
| "my_agent": { | ||
| "path": "../my_agent", | ||
| "setup": "uv sync", | ||
| "run": "uv run python -m src.main" | ||
| } | ||
| } | ||
| } |
3 changes: 3 additions & 0 deletions
3
...ng/microsoft-agents-testing/microsoft_agents/testing/presets/basic/e2e-tests/env.TEMPLATE
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 @@ | ||
| CONNECTIONS__SERVICE_CONNECTION__SETTINGS__CLIENTID= | ||
| CONNECTIONS__SERVICE_CONNECTION__SETTINGS__CLIENTSECRET= | ||
| CONNECTIONS__SERVICE_CONNECTION__SETTINGS__TENANTID= |
9 changes: 9 additions & 0 deletions
9
.../microsoft-agents-testing/microsoft_agents/testing/presets/basic/e2e-tests/pyproject.toml
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,9 @@ | ||
| [project] | ||
| name = "e2e-tests" | ||
| version = "0.0.0" | ||
| requires-python = ">=3.13" | ||
| dependencies = [ | ||
| "pytest", | ||
| "pytest-asyncio", | ||
| "microsoft-agents-testing @ git+https://github.com/microsoft/Agents-for-python.git@main#subdirectory=dev/testing/microsoft-agents-testing", | ||
| ] | ||
30 changes: 30 additions & 0 deletions
30
...ting/microsoft-agents-testing/microsoft_agents/testing/presets/basic/e2e-tests/pytest.ini
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 @@ | ||
| [pytest] | ||
| # pytest config for the environments/local test suite. | ||
| # Run locally: uv run pytest tests/ | ||
| # Or via Docker: ./scripts/run_local.ps1 | ||
|
|
||
| filterwarnings = | ||
| ignore::DeprecationWarning | ||
| ignore::PendingDeprecationWarning | ||
| ignore::aiohttp.web.NotAppKeyWarning | ||
|
|
||
| asyncio_mode = auto | ||
|
|
||
| addopts = | ||
| --strict-markers | ||
| --strict-config | ||
| --verbose | ||
| --tb=short | ||
| --durations=10 | ||
|
|
||
| minversion = 6.0 | ||
|
|
||
| markers = | ||
| unit: Unit tests | ||
| integration: Integration tests | ||
| slow: Slow tests that may take longer to run | ||
| requires_network: Tests that require network access | ||
| requires_auth: Tests that require authentication | ||
|
|
||
| asyncio_default_fixture_loop_scope = class | ||
| asyncio_default_test_loop_scope = class |
3 changes: 3 additions & 0 deletions
3
...crosoft-agents-testing/microsoft_agents/testing/presets/basic/e2e-tests/tests/__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 microsoft_agents.testing import scenario_registry | ||
|
|
||
| scenario_registry.load_json("config.json") | ||
|
rodrigobr-msft marked this conversation as resolved.
rodrigobr-msft marked this conversation as resolved.
|
||
11 changes: 11 additions & 0 deletions
11
...ft-agents-testing/microsoft_agents/testing/presets/basic/e2e-tests/tests/test_my_agent.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,11 @@ | ||
| import pytest | ||
|
|
||
| from microsoft_agents.testing import AgentClient | ||
|
|
||
| @pytest.mark.agent_test("my_agent") | ||
| async def test_my_agent(agent_client: AgentClient): | ||
|
|
||
| await agent_client.send("Hello, World!", wait=5.0) | ||
|
|
||
| # assert that the agent replied with a message Activity | ||
| agent_client.expect().that_for_any(type="message") |
3 changes: 3 additions & 0 deletions
3
...ing/microsoft-agents-testing/microsoft_agents/testing/presets/basic/my_agent/env.TEMPLATE
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 @@ | ||
| CONNECTIONS__SERVICE_CONNECTION__SETTINGS__CLIENTID= | ||
| CONNECTIONS__SERVICE_CONNECTION__SETTINGS__CLIENTSECRET= | ||
| CONNECTIONS__SERVICE_CONNECTION__SETTINGS__TENANTID= |
12 changes: 12 additions & 0 deletions
12
...g/microsoft-agents-testing/microsoft_agents/testing/presets/basic/my_agent/pyproject.toml
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 @@ | ||
| [project] | ||
| name = "my-agent" | ||
| version = "0.0.0" | ||
| requires-python = ">=3.13" | ||
|
rodrigobr-msft marked this conversation as resolved.
|
||
| dependencies = [ | ||
| "python-dotenv", | ||
| "aiohttp", | ||
| "microsoft-agents-hosting-aiohttp", | ||
| "microsoft-agents-hosting-core", | ||
| "microsoft-agents-authentication-msal", | ||
| "microsoft-agents-activity" | ||
| ] | ||
File renamed without changes.
61 changes: 61 additions & 0 deletions
61
...ting/microsoft-agents-testing/microsoft_agents/testing/presets/basic/my_agent/src/main.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,61 @@ | ||
| # Copyright (c) Microsoft Corporation. All rights reserved. | ||
| # Licensed under the MIT License. | ||
|
|
||
| import logging | ||
| from os import environ, path | ||
|
rodrigobr-msft marked this conversation as resolved.
|
||
| from dotenv import load_dotenv | ||
| from microsoft_agents.activity import load_configuration_from_env | ||
| from microsoft_agents.authentication.msal import ( | ||
| MsalConnectionManager, | ||
| ) | ||
| from microsoft_agents.hosting.core import ( | ||
| AgentApplication, | ||
| TurnState, | ||
| TurnContext, | ||
| MemoryStorage, | ||
| ) | ||
| from microsoft_agents.hosting.aiohttp import CloudAdapter | ||
| from microsoft_agents.hosting.core.app.oauth.authorization import Authorization | ||
|
|
||
| from .start_server import start_server | ||
|
|
||
| logging.basicConfig(level=logging.INFO) | ||
| load_dotenv() | ||
|
|
||
| agents_sdk_config = load_configuration_from_env(environ) | ||
|
|
||
| STORAGE = MemoryStorage() | ||
| CONNECTION_MANAGER = MsalConnectionManager(**agents_sdk_config) | ||
| ADAPTER = CloudAdapter(connection_manager=CONNECTION_MANAGER) | ||
| AUTHORIZATION = Authorization(STORAGE, CONNECTION_MANAGER, **agents_sdk_config) | ||
|
|
||
| AGENT_APP = AgentApplication[TurnState]( | ||
| storage=STORAGE, adapter=ADAPTER, authorization=AUTHORIZATION, **agents_sdk_config | ||
| ) | ||
|
|
||
|
|
||
| async def _help(context: TurnContext, _state: TurnState): | ||
| await context.send_activity( | ||
| "Welcome to the Echo Agent sample 🚀. " | ||
| "Type /help for help or send a message to see the echo feature in action." | ||
| ) | ||
|
|
||
|
|
||
| AGENT_APP.conversation_update("membersAdded")(_help) | ||
|
|
||
| AGENT_APP.message("/help")(_help) | ||
|
|
||
|
|
||
| @AGENT_APP.activity("message") | ||
| async def on_message(context: TurnContext, _): | ||
| await context.send_activity(f"you said: {context.activity.text}") | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| try: | ||
| start_server( | ||
| agent_application=AGENT_APP, | ||
| auth_configuration=CONNECTION_MANAGER.get_default_connection_configuration(), | ||
| ) | ||
| except Exception as error: | ||
| raise error | ||
|
rodrigobr-msft marked this conversation as resolved.
|
||
33 changes: 33 additions & 0 deletions
33
...rosoft-agents-testing/microsoft_agents/testing/presets/basic/my_agent/src/start_server.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,33 @@ | ||
| from os import environ | ||
| from microsoft_agents.hosting.core import AgentApplication, AgentAuthConfiguration | ||
| from microsoft_agents.hosting.aiohttp import ( | ||
| start_agent_process, | ||
| jwt_authorization_middleware, | ||
| CloudAdapter, | ||
| ) | ||
| from aiohttp.web import Request, Response, Application, run_app | ||
|
|
||
|
|
||
| def start_server( | ||
| agent_application: AgentApplication, auth_configuration: AgentAuthConfiguration | ||
| ): | ||
| async def entry_point(req: Request) -> Response: | ||
| agent: AgentApplication = req.app["agent_app"] | ||
| adapter: CloudAdapter = req.app["adapter"] | ||
| return await start_agent_process( | ||
| req, | ||
| agent, | ||
| adapter, | ||
| ) | ||
|
|
||
| APP = Application(middlewares=[jwt_authorization_middleware]) | ||
| APP.router.add_post("/api/messages", entry_point) | ||
| APP.router.add_get("/api/messages", lambda _: Response(status=200)) | ||
| APP["agent_configuration"] = auth_configuration | ||
| APP["agent_app"] = agent_application | ||
| APP["adapter"] = agent_application.adapter | ||
|
|
||
| try: | ||
| run_app(APP, host="localhost", port=environ.get("PORT", 3978)) | ||
| except Exception as error: | ||
| raise error | ||
|
rodrigobr-msft marked this conversation as resolved.
rodrigobr-msft marked this conversation as resolved.
rodrigobr-msft marked this conversation as resolved.
|
||
Oops, something went wrong.
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.