Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ def __init__(
"""
config_file: str = kwargs.get("filename", "")
if config_file:
kwargs = json.load(open(config_file))
with open(config_file) as f:
kwargs = json.load(f)
self.cosmos_db_endpoint: str = cosmos_db_endpoint or kwargs.get(
"cosmos_db_endpoint", ""
)
Expand Down
39 changes: 39 additions & 0 deletions pytest.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
[pytest]
# Pytest configuration for Microsoft Agents for Python

# Treat all warnings as errors by default
# This ensures that any code generating warnings will fail tests,
# promoting cleaner code and early detection of issues
filterwarnings =
error
# Ignore specific warnings that are not actionable or are from dependencies
ignore::DeprecationWarning:pkg_resources.*
ignore::DeprecationWarning:setuptools.*
ignore::PendingDeprecationWarning
# pytest-asyncio warnings that are safe to ignore
ignore:.*deprecated.*asyncio.*:DeprecationWarning:pytest_asyncio.*

# Test discovery configuration
testpaths = tests
python_files = test_*.py *_test.py
python_classes = Test*
python_functions = test_*

# Output configuration
addopts =
--strict-markers
--strict-config
--verbose
--tb=short
--durations=10

# Minimum version requirement
minversion = 6.0

# Markers for test categorization
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
21 changes: 21 additions & 0 deletions tests/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,27 @@

This document serves as a quick guide to the utilities we provide internally to test this SDK. More information will come with work on integration testing.

## Pytest Configuration

The project uses a `pytest.ini` configuration file in the root directory that sets up the following testing standards:

- **Warnings as Errors**: All warnings are treated as errors (`filterwarnings = error`) to ensure clean code and early detection of issues
- **Strict Configuration**: Uses `--strict-markers` and `--strict-config` to catch configuration issues
- **Test Discovery**: Automatically discovers tests in the `tests/` directory following standard naming conventions
- **Verbose Output**: Shows detailed test results with short tracebacks and duration information

To run tests locally:
```bash
# Run all tests
python -m pytest

# Run tests for a specific module
python -m pytest tests/activity/

# Run with custom options (these will be added to the configured defaults)
python -m pytest -x --lf # Stop on first failure, run last failed tests
```

## Storage Tests

More info soon. For now, there are flags defined in the code that dictate whether the Cosmos DB and the Blob storage tests are run, as these tests rely on local emulators.
Expand Down
30 changes: 15 additions & 15 deletions tests/_common/data/__init__.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
from .test_defaults import TEST_DEFAULTS
from .test_auth_data import (
TEST_AUTH_DATA,
from .default_test_values import DEFAULT_TEST_VALUES
from .auth_test_data import (
AUTH_TEST_DATA,
create_test_auth_handler,
)
from .test_storage_data import TEST_STORAGE_DATA
from .test_flow_data import TEST_FLOW_DATA
from .configs import TEST_ENV_DICT, TEST_ENV
from .configs import TEST_AGENTIC_ENV_DICT, TEST_AGENTIC_ENV
from .storage_test_data import STORAGE_TEST_DATA
from .flow_test_data import FLOW_TEST_DATA
from .configs import NON_AGENTIC_TEST_ENV_DICT, NON_AGENTIC_TEST_ENV
from .configs import AGENTIC_TEST_ENV_DICT, AGENTIC_TEST_ENV

__all__ = [
"TEST_DEFAULTS",
"TEST_AUTH_DATA",
"TEST_STORAGE_DATA",
"TEST_FLOW_DATA",
"DEFAULT_TEST_VALUES",
"AUTH_TEST_DATA",
"STORAGE_TEST_DATA",
"FLOW_TEST_DATA",
"create_test_auth_handler",
"TEST_ENV_DICT",
"TEST_ENV",
"TEST_AGENTIC_ENV_DICT",
"TEST_AGENTIC_ENV",
"NON_AGENTIC_TEST_ENV_DICT",
"NON_AGENTIC_TEST_ENV",
"AGENTIC_TEST_ENV_DICT",
"AGENTIC_TEST_ENV",
]
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ def create_test_auth_handler(
)


class TEST_AUTH_DATA:
class AUTH_TEST_DATA:
def __init__(self):

self.auth_handler: AuthHandler = create_test_auth_handler("graph")
Expand Down
11 changes: 8 additions & 3 deletions tests/_common/data/configs/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
from .test_auth_config import TEST_ENV_DICT, TEST_ENV
from .test_agentic_auth_config import TEST_AGENTIC_ENV_DICT, TEST_AGENTIC_ENV
from .test_auth_config import NON_AGENTIC_TEST_ENV_DICT, NON_AGENTIC_TEST_ENV
from .test_agentic_auth_config import AGENTIC_TEST_ENV_DICT, AGENTIC_TEST_ENV

__all__ = ["TEST_ENV_DICT", "TEST_ENV", "TEST_AGENTIC_ENV_DICT", "TEST_AGENTIC_ENV"]
__all__ = [
"NON_AGENTIC_TEST_ENV_DICT",
"NON_AGENTIC_TEST_ENV",
"AGENTIC_TEST_ENV_DICT",
"AGENTIC_TEST_ENV",
]
10 changes: 5 additions & 5 deletions tests/_common/data/configs/test_agentic_auth_config.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
from microsoft_agents.activity import load_configuration_from_env

from ...create_env_var_dict import create_env_var_dict
from ..test_defaults import TEST_DEFAULTS
from ..default_test_values import DEFAULT_TEST_VALUES

DEFAULTS = TEST_DEFAULTS()
DEFAULTS = DEFAULT_TEST_VALUES()

_TEST_AGENTIC_ENV_RAW = """
CONNECTIONS__SERVICE_CONNECTION__SETTINGS__TENANTID=service-tenant-id
Expand Down Expand Up @@ -46,9 +46,9 @@
)


def TEST_AGENTIC_ENV():
def AGENTIC_TEST_ENV():
return create_env_var_dict(_TEST_AGENTIC_ENV_RAW)


def TEST_AGENTIC_ENV_DICT():
return load_configuration_from_env(TEST_AGENTIC_ENV())
def AGENTIC_TEST_ENV_DICT():
return load_configuration_from_env(AGENTIC_TEST_ENV())
10 changes: 5 additions & 5 deletions tests/_common/data/configs/test_auth_config.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
from microsoft_agents.activity import load_configuration_from_env

from ...create_env_var_dict import create_env_var_dict
from ..test_defaults import TEST_DEFAULTS
from ..default_test_values import DEFAULT_TEST_VALUES

DEFAULTS = TEST_DEFAULTS()
DEFAULTS = DEFAULT_TEST_VALUES()

_TEST_ENV_RAW = """
AGENTAPPLICATION__USERAUTHORIZATION__HANDLERS__{auth_handler_id}__SETTINGS__AZUREBOTOAUTHCONNECTIONNAME={abs_oauth_connection_name}
Expand All @@ -20,9 +20,9 @@
)


def TEST_ENV():
def NON_AGENTIC_TEST_ENV():
return create_env_var_dict(_TEST_ENV_RAW)


def TEST_ENV_DICT():
return load_configuration_from_env(TEST_ENV())
def NON_AGENTIC_TEST_ENV_DICT():
return load_configuration_from_env(NON_AGENTIC_TEST_ENV())
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
)


class TEST_DEFAULTS:
class DEFAULT_TEST_VALUES:
def __init__(self):

self.token = "__token"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
from microsoft_agents.hosting.core._oauth import _FlowState, _FlowStateTag

from tests._common.storage import MockStoreItem
from tests._common.data.test_defaults import TEST_DEFAULTS
from tests._common.data.default_test_values import DEFAULT_TEST_VALUES

DEFAULTS = TEST_DEFAULTS()
DEFAULTS = DEFAULT_TEST_VALUES()

DEF_FLOW_ARGS = {
"ms_app_id": DEFAULTS.ms_app_id,
Expand All @@ -15,7 +15,7 @@
}


class TEST_FLOW_DATA:
class FLOW_TEST_DATA:
def __init__(self):

self.not_started = _FlowState(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@

from tests._common.storage import MockStoreItem

from .test_flow_data import (
TEST_FLOW_DATA,
from .flow_test_data import (
FLOW_TEST_DATA,
update_flow_state_handler,
flow_key,
)

FLOW_DATA = TEST_FLOW_DATA()
FLOW_DATA = FLOW_TEST_DATA()


class TEST_STORAGE_DATA:
class STORAGE_TEST_DATA:
def __init__(self):

self.dict = {
Expand Down
4 changes: 2 additions & 2 deletions tests/_common/fixtures/flow_state_fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

from microsoft_agents.hosting.core._oauth import _FlowStateTag

from tests._common.data import TEST_FLOW_DATA
from tests._common.data import FLOW_TEST_DATA

FLOW_STATES = TEST_FLOW_DATA()
FLOW_STATES = FLOW_TEST_DATA()


class FlowStateFixtures:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@
T = TypeVar("T")


# currently unused (probably outdated)
# but may be useful to bring up-to-date for future testing scenarios
class TestClient:
# This is a currently unused (probably outdated & deleted) test client that
# may be useful to bring up-to-date for future testing scenarios.
class ObsoleteTestClient:
"""
A testing channel that connects directly to an adapter.

Expand Down
8 changes: 4 additions & 4 deletions tests/_common/testing_objects/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from .adapters import TestingAdapter
from .adapters import MockTestingAdapter

from .mocks import (
MockMsalAuth,
Expand All @@ -14,7 +14,7 @@

from .testing_authorization import TestingAuthorization
from .testing_connection_manager import TestingConnectionManager
from .testing_custom_state import TestingCustomState
from .mock_testing_custom_state import MockTestingCustomState
from .testing_token_provider import TestingTokenProvider
from .testing_user_token_client import TestingUserTokenClient

Expand All @@ -26,10 +26,10 @@
"mock_class_UserTokenClient",
"TestingAuthorization",
"TestingConnectionManager",
"TestingCustomState",
"MockTestingCustomState",
"TestingTokenProvider",
"TestingUserTokenClient",
"TestingAdapter",
"MockTestingAdapter",
"mock_class_UserAuthorization",
"mock_class_AgenticUserAuthorization",
"mock_class_Authorization",
Expand Down
4 changes: 2 additions & 2 deletions tests/_common/testing_objects/adapters/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
from .testing_adapter import TestingAdapter
from .mock_testing_adapter import MockTestingAdapter

__all__ = ["TestingAdapter"]
__all__ = ["MockTestingAdapter"]
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
AgentCallbackHandler = Callable[[TurnContext], Awaitable]


class TestingAdapter(ChannelAdapter):
class MockTestingAdapter(ChannelAdapter):
"""
A mock adapter that can be used for unit testing of agent logic.
"""
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from microsoft_agents.hosting.core import AgentState, Storage, StoreItem, TurnContext


class TestingCustomState(AgentState):
class MockTestingCustomState(AgentState):
"""Custom state implementation for testing."""

def __init__(self, storage: Storage, namespace: str = ""):
Expand Down
4 changes: 2 additions & 2 deletions tests/_common/testing_objects/mocks/mock_oauth_flow.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
from microsoft_agents.activity import TokenResponse
from microsoft_agents.hosting.core._oauth import _OAuthFlow

from tests._common.data import TEST_DEFAULTS
from tests._common.data import DEFAULT_TEST_VALUES

DEFAULTS = TEST_DEFAULTS()
DEFAULTS = DEFAULT_TEST_VALUES()


def mock_OAuthFlow(
Expand Down
4 changes: 2 additions & 2 deletions tests/_integration/common/testing_environment.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

from tests._common.testing_objects import (
TestingConnectionManager,
TestingAdapter,
MockTestingAdapter,
)


Expand Down Expand Up @@ -62,7 +62,7 @@ def __init__(self, mocker):

self.storage = MemoryStorage()
self.connection_manager = TestingConnectionManager()
self.adapter = TestingAdapter()
self.adapter = MockTestingAdapter()
self.authorization = Authorization(
self.storage, self.connection_manager, **agents_sdk_config
)
Expand Down
5 changes: 2 additions & 3 deletions tests/activity/test_activity.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@

from tests.activity._common.my_channel_data import MyChannelData
from tests.activity._common.testing_activity import create_test_activity
from tests._common.data import TEST_DEFAULTS
from tests._common.data import DEFAULT_TEST_VALUES

DEFAULTS = TEST_DEFAULTS()
DEFAULTS = DEFAULT_TEST_VALUES()


def helper_validate_recipient_and_from(
Expand Down Expand Up @@ -416,7 +416,6 @@ def test_get_product_info_entity_single(self, entities, expected):


class TestActivityAgenticOps:

@pytest.fixture(params=[RoleTypes.user, RoleTypes.skill, RoleTypes.agent])
def non_agentic_role(self, request):
return request.param
Expand Down
5 changes: 2 additions & 3 deletions tests/activity/test_channel_id.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,12 @@

from microsoft_agents.activity import ChannelId

from tests._common.data import TEST_DEFAULTS
from tests._common.data import DEFAULT_TEST_VALUES

DEFAULTS = TEST_DEFAULTS()
DEFAULTS = DEFAULT_TEST_VALUES()


class TestChannelId:

def test_init_from_str(self):
channel_id = ChannelId("email:support")
assert channel_id.channel == "email"
Expand Down
4 changes: 2 additions & 2 deletions tests/activity/test_load_configuration.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
from microsoft_agents.activity import load_configuration_from_env

from tests._common import create_env_var_dict
from tests._common.data import TEST_DEFAULTS
from tests._common.data import DEFAULT_TEST_VALUES

DEFAULTS = TEST_DEFAULTS()
DEFAULTS = DEFAULT_TEST_VALUES()

ENV_DICT = {
"CONNECTIONS": {
Expand Down
Loading