Skip to content

Commit dc9aad7

Browse files
Reorganizing shared utilities for testing (#134)
* TestingEnvironment and SDKFixtures classes for testing * Changing env setup for OAuthFlow tests * Completed OAuthFlow tests revamp * README draft * More changes to README * Reorganizing mock objects * Simplifying testing utilities * Creating sample test flows outline * Fixing tests with reorganized testing structure * Adding README.md
1 parent 5aafeba commit dc9aad7

80 files changed

Lines changed: 2062 additions & 1503 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.pre-commit-config.yaml

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,4 @@ repos:
33
rev: 22.3.0 # Use the latest stable version of Black
44
hooks:
55
- id: black
6-
args: [--line-length=88] # Adjust line length as needed
7-
- repo: https://github.com/pycqa/flake8
8-
rev: 7.2.0 # pick a git hash / tag to point to
9-
hooks:
10-
- id: flake8
6+
args: [--line-length=88] # Adjust line length as needed

tests/README.md

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
# Agents SDK for Python Testing
2+
3+
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.
4+
5+
## Storage Tests
6+
7+
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.
8+
9+
## Mocking
10+
11+
When using a class or function that takes a `mocker` argument, it is highly recommended that you pass in the Pytest fixture obtained either in:
12+
13+
a test
14+
15+
```python
16+
def test_thing(self, some_fixture, mocker):
17+
mock_UserTokenClient(mocker)
18+
```
19+
20+
the setup method of a class
21+
22+
```python
23+
class TestThing:
24+
25+
def setup_method(self, mocker):
26+
self.msal_auth = MockMsalAuth(mocker)
27+
```
28+
29+
or in another fixture
30+
31+
```python
32+
@pytest.fixture
33+
def user_token_client(self, mocker):
34+
return mock_OAuthFlow(mocker, get_user_token_return="token")
35+
```
36+
37+
This ensures Pytest will correctly manage the lifetime of your mocking logic to occur within the score of the individual test or class.
38+
39+
## Directory Structure
40+
41+
42+
### Module Names
43+
44+
This directory follows the same structure as the package structure. If there is a test module that tests the functionality of a module in the packages source code, then please use the format `test_{ORIGINAL_MODULE}.py` file naming convention. If a module is an extra module that only exists in testing and has no counterpart in the packages source code, then it is encouraged that you prefix it with an underscore. The only exception is if a parent (or ancestor) directory of the testing Python file already has an underscore prefix. For example:
45+
46+
```
47+
microsoft_agents/hosting/core
48+
__init__.py
49+
50+
_common/
51+
__init__.py
52+
bar.py
53+
54+
app/
55+
__init__.py
56+
_helper.py
57+
test_agent_application.py
58+
59+
_foo.py
60+
test_turn_context.py
61+
test_utils.py
62+
63+
```
64+
65+
### `tests/_common`
66+
67+
This directory contains common utilities for testing.
68+
69+
### `tests/_common/_tests`
70+
71+
Tests for testing utilities.
72+
73+
### `tests/_common/data`
74+
75+
Here, we encourage defining the data within the constructors of a class. I guess this helps clean up imports, but the primary purpose is to prevent tests from mutating these testing constants and interfering with other tests. The `test_defaults.py` module defines defaults for fundamental variables such as `user_id` and `channel_id`. These defaults are used in tests as well as other data constructors in `tests/_common/data`. For instance `test_flow_data.py` builds on those defaults to define FlowState objects for testing, and then `tests/_common/storage_data` builds even further on that.
76+
77+
### `tests/_common/storage`
78+
79+
Storage related functionality. This was the first shared testing utility module, so this can eventually be reorganized into the rest of the `tests/_common` structure.
80+
81+
### `tests/_common/fixtures`
82+
83+
This directory holds common fixtures that might be useful. For instance, `FlowStateFixtures` provides fixtures that are useful for testing both the OAuthFlow and Authorization classes, and it relies on `tests/_common/data/test_flow_data.py` module.
84+
85+
### `tests/_common/testing_objects`
86+
87+
This directory contains implementations and functions to construct objects that implement/extend core Protocols or mock existing functionality. In this repo, `testing_{class_name}.py` modules contain simple implementations with predictable behavior while `mock_{class_name}.py` usually contain `mock_{class_name}` and `mock_class_{class_name}` functions that wrap existing instances/classes with Pytest's mocking capabilities.
88+
89+
### `tests/_integration`
90+
91+
At the moment, there is no actual real integration testing, but there is a foundation that lets you define an environmental setup and then run a "sample" on that environment.

tests/_common/__init__.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
from .approx_equal import approx_eq
2+
3+
__all__ = [
4+
"approx_eq",
5+
]

tests/_common/_tests/data/__init__.py

Whitespace-only changes.

tests/_common/_tests/data/test_flow_states.py

Whitespace-only changes.

tests/_common/_tests/data/test_storage_data.py

Whitespace-only changes.

tests/_common/_tests/storage/__init__.py

Whitespace-only changes.
File renamed without changes.

0 commit comments

Comments
 (0)