Skip to content
Draft
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
3cb2022
Prelim work to handle sending invokes
rodrigobr-msft Dec 1, 2025
6e25a90
Reorganizing AgentClient interface
rodrigobr-msft Dec 1, 2025
fd25c32
Removing AutoClient file
rodrigobr-msft Dec 1, 2025
464ecc6
Adding basic stream activity handling for ResponseClient
rodrigobr-msft Dec 1, 2025
d1ec76e
CLI starter
rodrigobr-msft Dec 1, 2025
6c0a56e
Adding input response handling for DDT
rodrigobr-msft Dec 1, 2025
6a57b4c
Adding resolve_env utility function
rodrigobr-msft Dec 1, 2025
943fd71
Fixing test cases
rodrigobr-msft Dec 1, 2025
efc7da2
Handling of InvokeResponse assertions in DataDrivenTest class
rodrigobr-msft Dec 1, 2025
5c77c65
Expect replies tests for DDT
rodrigobr-msft Dec 2, 2025
ecb2c6e
Fixing integration tests
rodrigobr-msft Dec 2, 2025
3048e19
Fixing integration tests with streaming
rodrigobr-msft Dec 2, 2025
930bf09
More adjustments to test cases
rodrigobr-msft Dec 2, 2025
603050d
Adding CopilotClient test case using integration package features
rodrigobr-msft Dec 5, 2025
415264b
Reformatting
rodrigobr-msft Dec 5, 2025
cadb843
CLI grouping
rodrigobr-msft Dec 5, 2025
902d412
Moving ResponseClient to use AiohttpRunner instead of async version
rodrigobr-msft Dec 5, 2025
b373f31
Created DDT cli command
rodrigobr-msft Dec 6, 2025
5329bc4
Adding executor and CLI unit tests
rodrigobr-msft Dec 8, 2025
a37a136
Adding create_payload_sender test
rodrigobr-msft Dec 8, 2025
bcca57f
Implementing auth_test command
rodrigobr-msft Dec 8, 2025
4be418a
Finalizing auth sample from cli
rodrigobr-msft Dec 8, 2025
329fefa
Updating README
rodrigobr-msft Dec 8, 2025
4e8dca3
Reorganizing SDK tests
rodrigobr-msft Dec 8, 2025
61739f4
Revising assertion core
rodrigobr-msft Dec 9, 2025
223a1f8
Selector changes
rodrigobr-msft Dec 9, 2025
fae00e9
Unset and DynamicObject refined
rodrigobr-msft Dec 9, 2025
2d6a9eb
expand function implementation
rodrigobr-msft Dec 9, 2025
a4e3a25
Evaluation implementation steps
rodrigobr-msft Dec 9, 2025
12f9d90
Assertion evaluation fixes
rodrigobr-msft Dec 9, 2025
995d44e
Robust query function handling
rodrigobr-msft Dec 10, 2025
f077099
Adding documentation
rodrigobr-msft Dec 10, 2025
209c56d
Adding AssertionContext tests
rodrigobr-msft Dec 10, 2025
31d5f2f
Assertions tests
rodrigobr-msft Dec 10, 2025
73205e0
Adding basic fixtures
rodrigobr-msft Dec 10, 2025
42846ed
Stable version
rodrigobr-msft Dec 10, 2025
ba50824
Updating old tests
rodrigobr-msft Dec 16, 2025
8dc344c
Merge branch 'main' of https://github.com/microsoft/Agents-for-python…
rodrigobr-msft Dec 16, 2025
ba92b0b
Adding CopilotClient integration test
rodrigobr-msft Dec 16, 2025
66b818c
Quickstart E2E test port
rodrigobr-msft Dec 16, 2025
284ab17
Fixed wrong model query in test case
rodrigobr-msft Dec 16, 2025
a21a856
Added FutureVars
rodrigobr-msft Dec 17, 2025
54c4981
Porting test cases
rodrigobr-msft Jan 5, 2026
16b3366
Fixing implementation of AgentClient.send_invoke_activity
rodrigobr-msft Jan 7, 2026
055367a
Ported webchat and msteams tests
rodrigobr-msft Jan 7, 2026
df11807
Removing test cases in old format
rodrigobr-msft Jan 7, 2026
a70cbe7
Adding docs
rodrigobr-msft Jan 8, 2026
bc55f30
Adding code for quickly running an interactive agent
rodrigobr-msft Jan 9, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
File renamed without changes.
2 changes: 0 additions & 2 deletions dev/integration/samples/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
from .basic_sample import BasicSample
from .quickstart_sample import QuickstartSample

__all__ = [
"BasicSample",
"QuickstartSample",
]
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ test:
name: Test Bot
text: hi 5
locale: en-US
- skip
- type: assertion
quantifier: one
activity:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@ test:
name: Bot
text: 'w: What''s the weather in Seattle today?'
locale: en-US
- type: skip
- type: assertion
selector:
index: -1
activity:
attachments:
- contentType: application/vnd.microsoft.card.adaptive
activity:
type: message
attachments:
- contentType: application/vnd.microsoft.card.adaptive
content: ["RE_MATCH", "(�|\\u00B0|Missing temperature inside adaptive card:)"]
- content: ["RE_MATCH", "(�|\\u00B0|Missing temperature inside adaptive card:)"]
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,16 @@ test:
name: Bot
text: poem
locale: en-US
- type: skip
# - type: assertion
# selector:
# activity:
# type: typing
# activity:
# text: ["CONTAINS", "Hold on for an awesome poem about Apollo"]
# - type: assertion
# selector:
# index: -1
# activity:
# text: ["CONTAINS", "Apollo"]
# - type: breakpoint
- type: assertion
selector:
activity:
type: typing
quantifier: any
activity:
text: ["CONTAINS", "Hold on for an awesome poem about Apollo"]
- type: assertion
selector:
index: -1
activity:
text: ["CONTAINS", "Apollo"]
- type: breakpoint
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,10 @@ test:
locale: en-US
- type: assertion
invokeResponse:
composeExtension:
type: result
text: ["CONTAINS", "Newtonsoft.Json"]
attachments:
contentType: application/vnd.microsoft.card.thumbnail
body:
composeExtension:
type: result
text: ["CONTAINS", "Newtonsoft.Json"]
attachments:
contentType: application/vnd.microsoft.card.thumbnail
- type: skip
10 changes: 6 additions & 4 deletions dev/integration/tests/basic_agent/test_basic_agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@
Integration,
)

TEST_BASIC_AGENT = True

@ddt("tests/basic_agent/directline", prefix="directline")
@ddt("tests/basic_agent/webchat", prefix="webchat")
@ddt("tests/basic_agent/msteams", prefix="msteams")
class TestBasicAgent(Integration):
# @ddt("tests/basic_agent/webchat", prefix="webchat")
# @ddt("tests/basic_agent/msteams", prefix="msteams")
@pytest.mark.skipif(not TEST_BASIC_AGENT, reason="Skipping external agent tests for now.")
class TestBasicAgentExternal(Integration):
_agent_url = "http://localhost:3978/"
_service_url = "http://localhost:8001/"
_config_path = "agents/basic_agent/python/.env"
_config_path = "agents/basic_agent/python/.env"
5 changes: 0 additions & 5 deletions dev/integration/tests/quickstart/test_quickstart_sample.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,3 @@
class TestQuickstartDirectline(Integration):
_sample_cls = QuickstartSample
_environment_cls = AiohttpEnvironment


@ddt("tests/quickstart/directline")
@pytest.mark.skipif(True, reason="Skipping external agent tests for now.")
class TestQuickstartExternalDirectline(Integration): ...
22 changes: 6 additions & 16 deletions dev/integration/tests/test_expect_replies.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import pytest
import logging

from microsoft_agents.activity import Activity

Expand All @@ -9,20 +8,11 @@
AiohttpEnvironment,
)

from ..samples import BasicSample
from ..samples import QuickstartSample


class BasicSampleWithLogging(BasicSample):

async def init_app(self):

logging.getLogger("microsoft_agents").setLevel(logging.DEBUG)

await super().init_app()


class TestBasicDirectline(Integration):
_sample_cls = BasicSampleWithLogging
class TestExpectReplies(Integration):
_sample_cls = QuickstartSample
_environment_cls = AiohttpEnvironment

@pytest.mark.asyncio
Expand All @@ -36,12 +26,12 @@ async def test_expect_replies_without_service_url(
conversation={"id": "conv-id"},
channel_id="test",
from_property={"id": "from-id"},
to={"id": "to-id"},
recipient={"id": "to-id"},
delivery_mode="expectReplies",
locale="en-US",
)

res = await agent_client.send_expect_replies(activity)

breakpoint()
res = Activity.model_validate(res)
assert len(res) > 0
assert isinstance(res[0], Activity)
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

from .assertions import (
ModelAssertion,
Selector,
ModelSelector,
AssertionQuantifier,
assert_model,
assert_field,
Expand All @@ -31,6 +31,8 @@
DataDrivenTest,
)

from .cli import cli
Copy link

Copilot AI Dec 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The module cli is being imported and exported in __init__.py, but cli.py is an empty file. This will cause the import to succeed but cli will be an empty module object with no useful functionality. Either implement the CLI functionality in this file or remove the import/export from __init__.py.

Copilot uses AI. Check for mistakes.
Copy link

Copilot AI Dec 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Importing from .cli which is an empty file (cli.py has 0 lines). This will cause an ImportError when the module is imported. The cli module needs to be properly defined or this import should be removed.

Copilot uses AI. Check for mistakes.

__all__ = [
"SDKConfig",
"generate_token",
Expand All @@ -45,7 +47,7 @@
"populate_activity",
"get_host_and_port",
"ModelAssertion",
"Selector",
"ModelSelector",
"AssertionQuantifier",
"assert_model",
"assert_field",
Expand All @@ -56,4 +58,5 @@
"FieldAssertionType",
"ddt",
"DataDrivenTest",
"cli",
Copy link

Copilot AI Dec 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Exporting cli in __all__ but it's imported from an empty module. This will cause an ImportError. Either implement the cli module or remove this export.

Copilot uses AI. Check for mistakes.
]
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@
or (a is UNSET_FIELD and b is not None),
FieldAssertionType.GREATER_THAN: lambda a, b: a > b,
FieldAssertionType.LESS_THAN: lambda a, b: a < b,
FieldAssertionType.CONTAINS: lambda a, b: b in a,
FieldAssertionType.NOT_CONTAINS: lambda a, b: b not in a,
FieldAssertionType.CONTAINS: lambda a, b: b in a if a is not UNSET_FIELD else False,
FieldAssertionType.NOT_CONTAINS: lambda a, b: b not in a if a is not UNSET_FIELD else True,
FieldAssertionType.RE_MATCH: lambda a, b: re.match(b, a) is not None,
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,12 @@ def _check(
assertion, assertion_type = _parse_assertion(baseline)

if assertion_type is None:

if isinstance(baseline, dict):

if actual is UNSET_FIELD:
actual = {}

for key in baseline:
new_field_path = f"{field_path}.{key}" if field_path else key
new_actual = actual.get(key, UNSET_FIELD)
Expand All @@ -38,6 +43,10 @@ def _check(
return True, None

elif isinstance(baseline, list):

Copy link

Copilot AI Dec 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Trailing whitespace on this line should be removed.

Suggested change

Copilot uses AI. Check for mistakes.
if actual is UNSET_FIELD:
actual = []

for index, item in enumerate(baseline):
new_field_path = (
f"{field_path}[{index}]" if field_path else f"[{index}]"
Expand Down
File renamed without changes.
File renamed without changes.
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import os

from dotenv import load_dotenv

from microsoft_agents.hosting.core import AgentApplication, TurnContext, TurnState

from microsoft_agents.testing.integration.core.sample import Sample


def create_auth_route(auth_handler_id: str, agent: AgentApplication):
def dynamic_function(context: TurnContext, state: TurnState):
Copy link

Copilot AI Dec 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The function dynamic_function is defined as a regular function but uses await on line 12, making it an async function. This will cause a SyntaxError.

Change line 11 to:

async def dynamic_function(context: TurnContext, state: TurnState):
Suggested change
def dynamic_function(context: TurnContext, state: TurnState):
async def dynamic_function(context: TurnContext, state: TurnState):

Copilot uses AI. Check for mistakes.
Copy link

Copilot AI Dec 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing async keyword on function definition. The function dynamic_function uses await on line 12 but is not declared as async. This will cause a SyntaxError at runtime.

Copilot uses AI. Check for mistakes.
token = await agent.auth.get_token(context, state, auth_handler_id)
Copy link

Copilot AI Dec 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The dynamic_function is defined as a synchronous function but uses await. This function should be declared as async def.

Copilot uses AI. Check for mistakes.

return f"Hello from {auth_handler_id}! Token: {token}"

dynamic_function.__name__ = f"auth_route_{auth_handler_id}".lower()
return dynamic_function


class QuickstartSample(Sample):
"""A quickstart sample implementation."""
Copy link

Copilot AI Dec 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The class is named QuickstartSample but should be AuthSample based on the file name and context. Additionally, the docstring "A quickstart sample implementation." doesn't accurately describe this authentication-specific sample.

Copilot uses AI. Check for mistakes.

@classmethod
async def get_config(cls) -> dict:
"""Retrieve the configuration for the sample."""
load_dotenv("./src/tests/.env")
return dict(os.environ)
Copy link

Copilot AI Dec 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing async keyword in function definition. The function contains await on line 12 but is not declared as async, which will cause a SyntaxError.

Change the function signature to:

@classmethod
async def get_config(cls) -> dict:

Copilot uses AI. Check for mistakes.

async def init_app(self):
"""Initialize the application for the quickstart sample."""

app: AgentApplication[TurnState] = self.env.agent_application

for auth_handler in app.config.authentication_handlers:
app.message(
auth_handler.name.lower(),
create_auth_route(auth_handler.name),
Copy link

Copilot AI Dec 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Call to function create_auth_route with too few arguments; should be no fewer than 2.

Suggested change
create_auth_route(auth_handler.name),
create_auth_route(auth_handler.name, app),

Copilot uses AI. Check for mistakes.
Copy link

Copilot AI Dec 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Call to function create_auth_route with too few arguments; should be no fewer than 2.

Copilot uses AI. Check for mistakes.
auth_handlers=[auth_handler.name],
)
Copy link

Copilot AI Dec 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file appears to be a duplicate of dev/microsoft-agents-testing/microsoft_agents/testing/cli/test_auth/auth_sample.py. Having identical code in two locations creates a maintenance burden. Consider consolidating these files or clarifying their distinct purposes.

Copilot uses AI. Check for mistakes.
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import cli
Copy link

Copilot AI Dec 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The import statement import cli will fail because there is no module named cli in scope or in the standard library. This appears to be an incomplete test file.

If this is meant to import from the local package, it should be:

from microsoft_agents.testing import cli

or similar, depending on the intended module structure.

Suggested change
import cli
from microsoft_agents.testing import cli

Copilot uses AI. Check for mistakes.
Copy link

Copilot AI Dec 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Import of 'cli' is not used.

Suggested change
import cli

Copilot uses AI. Check for mistakes.
Copy link

Copilot AI Dec 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The import statement import cli will fail because cli is not a valid module. This appears to be an incomplete or incorrect import that should either import from .cli or be removed entirely.

Copilot uses AI. Check for mistakes.
Copy link

Copilot AI Dec 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Import of 'cli' is not used.

Copilot uses AI. Check for mistakes.


def test_auth():
pass
Copy link

Copilot AI Dec 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test function test_auth() is empty and provides no test coverage. This placeholder test should either be implemented or removed to avoid misleading test results.

Copilot uses AI. Check for mistakes.
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import os

from dotenv import load_dotenv

from microsoft_agents.hosting.core import AgentApplication, TurnContext, TurnState

from microsoft_agents.testing.integration.core.sample import Sample


def create_auth_route(auth_handler_id: str, agent: AgentApplication):
def dynamic_function(context: TurnContext, state: TurnState):
Copy link

Copilot AI Dec 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing async keyword on function definition. The function dynamic_function uses await on line 12 but is not declared as async. This will cause a SyntaxError at runtime.

Copilot uses AI. Check for mistakes.
token = await agent.auth.get_token(context, state, auth_handler_id)
Copy link

Copilot AI Dec 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The dynamic_function is defined as a synchronous function but uses await. This function should be declared as async def.

Copilot uses AI. Check for mistakes.

return f"Hello from {auth_handler_id}! Token: {token}"

dynamic_function.__name__ = f"auth_route_{auth_handler_id}".lower()
return dynamic_function


class QuickstartSample(Sample):
Copy link

Copilot AI Dec 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The class is named QuickstartSample but the docstring says "A quickstart sample implementation." This appears to be incorrect - based on the file name auth_sample.py and the authentication-specific logic, this should likely be named AuthSample to match the import in command.py.

Copilot uses AI. Check for mistakes.
"""A quickstart sample implementation."""

@classmethod
async def get_config(cls) -> dict:
"""Retrieve the configuration for the sample."""
load_dotenv("./src/tests/.env")
return dict(os.environ)

async def init_app(self):
"""Initialize the application for the quickstart sample."""

app: AgentApplication[TurnState] = self.env.agent_application

for auth_handler in app.config.authentication_handlers:
app.message(
auth_handler.name.lower(),
create_auth_route(auth_handler.name),
Copy link

Copilot AI Dec 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Call to function create_auth_route with too few arguments; should be no fewer than 2.

Copilot uses AI. Check for mistakes.
auth_handlers=[auth_handler.name],
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import click

from .auth_sample import AuthSample
Copy link

Copilot AI Dec 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AuthSample class is not defined in this module. Line 3 imports AuthSample from .auth_sample, but the file auth_sample.py defines a class named QuickstartSample, not AuthSample. This will cause an ImportError at runtime.

Copilot uses AI. Check for mistakes.

from microsoft_agents.testing.utils import resolve_env
from microsoft_agents.testing.core import AiohttpEnvironment
Copy link

Copilot AI Dec 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Invalid import path. The import from microsoft_agents.testing.core import AiohttpEnvironment appears to be incorrect. Based on the codebase structure, the correct import should be from microsoft_agents.testing.integration.core import AiohttpEnvironment.

Copilot uses AI. Check for mistakes.

@click.command()
def auth_test():
"""Run authentication sample test."""

environment = AiohttpEnvironment()
environment.setup()

sample = AuthSample()
sample.run(resolve_env)
Copy link

Copilot AI Dec 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The sample.run(resolve_env) call appears incorrect. The run method likely expects a configuration dictionary, not the resolve_env function itself. This should probably be sample.run(resolve_env(config_path)) or similar.

Copilot uses AI. Check for mistakes.
Loading