mcp-proxy-adapter 2.1.2__py3-none-any.whl → 2.1.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {examples → mcp_proxy_adapter/examples}/openapi_server.py +35 -7
- {mcp_proxy_adapter-2.1.2.dist-info → mcp_proxy_adapter-2.1.4.dist-info}/METADATA +98 -2
- mcp_proxy_adapter-2.1.4.dist-info/RECORD +28 -0
- mcp_proxy_adapter-2.1.4.dist-info/top_level.txt +1 -0
- docs/README.md +0 -172
- docs/README_ru.md +0 -172
- docs/architecture.md +0 -251
- docs/architecture_ru.md +0 -343
- docs/command_development.md +0 -250
- docs/command_development_ru.md +0 -593
- docs/deployment.md +0 -251
- docs/deployment_ru.md +0 -1298
- docs/examples.md +0 -254
- docs/examples_ru.md +0 -401
- docs/mcp_proxy_adapter.md +0 -251
- docs/mcp_proxy_adapter_ru.md +0 -405
- docs/quickstart.md +0 -251
- docs/quickstart_ru.md +0 -397
- docs/testing.md +0 -255
- docs/testing_ru.md +0 -469
- docs/validation_ru.md +0 -287
- examples/mcp_proxy_config.json +0 -175
- mcp_proxy_adapter-2.1.2.dist-info/RECORD +0 -61
- mcp_proxy_adapter-2.1.2.dist-info/top_level.txt +0 -5
- scripts/code_analyzer/code_analyzer.py +0 -328
- scripts/code_analyzer/register_commands.py +0 -446
- scripts/publish.py +0 -85
- tests/conftest.py +0 -12
- tests/test_adapter.py +0 -529
- tests/test_adapter_coverage.py +0 -274
- tests/test_basic_dispatcher.py +0 -169
- tests/test_command_registry.py +0 -328
- tests/test_examples.py +0 -32
- tests/test_mcp_proxy_adapter.py +0 -568
- tests/test_mcp_proxy_adapter_basic.py +0 -262
- tests/test_part1.py +0 -348
- tests/test_part2.py +0 -524
- tests/test_schema.py +0 -358
- tests/test_simple_adapter.py +0 -251
- {examples → mcp_proxy_adapter/examples}/analyze_config.py +0 -0
- {examples → mcp_proxy_adapter/examples}/basic_integration.py +0 -0
- {examples → mcp_proxy_adapter/examples}/docstring_and_schema_example.py +0 -0
- {examples → mcp_proxy_adapter/examples}/extension_example.py +0 -0
- {examples → mcp_proxy_adapter/examples}/help_best_practices.py +0 -0
- {examples → mcp_proxy_adapter/examples}/help_usage.py +0 -0
- {examples → mcp_proxy_adapter/examples}/mcp_proxy_client.py +0 -0
- {examples → mcp_proxy_adapter/examples}/project_structure_example.py +0 -0
- {examples → mcp_proxy_adapter/examples}/testing_example.py +0 -0
- {mcp_proxy_adapter-2.1.2.dist-info → mcp_proxy_adapter-2.1.4.dist-info}/WHEEL +0 -0
- {mcp_proxy_adapter-2.1.2.dist-info → mcp_proxy_adapter-2.1.4.dist-info}/licenses/LICENSE +0 -0
docs/testing.md
DELETED
@@ -1,255 +0,0 @@
|
|
1
|
-
# Command Testing Guide
|
2
|
-
|
3
|
-
This guide describes approaches and best practices for testing commands registered in Command Registry.
|
4
|
-
|
5
|
-
## Why Testing Commands is Important
|
6
|
-
|
7
|
-
Commands in Command Registry often represent key business operations of the application. Testing them has the following advantages:
|
8
|
-
|
9
|
-
1. **Reliability** - verifying command functionality in various conditions
|
10
|
-
2. **Documentation** - tests demonstrate expected command behavior
|
11
|
-
3. **Regression** - preventing regressions when making changes
|
12
|
-
4. **Refactoring** - ability to safely improve command code
|
13
|
-
5. **Validation** - verifying correct handling of input parameters and errors
|
14
|
-
|
15
|
-
## Testing Levels
|
16
|
-
|
17
|
-
### 1. Unit Testing
|
18
|
-
|
19
|
-
Testing individual command functions in isolation from other components.
|
20
|
-
|
21
|
-
```python
|
22
|
-
import pytest
|
23
|
-
from myapp.commands.math_commands import add_numbers
|
24
|
-
|
25
|
-
def test_add_numbers_basic():
|
26
|
-
# Basic scenario
|
27
|
-
result = add_numbers(5, 3)
|
28
|
-
assert result == 8
|
29
|
-
|
30
|
-
def test_add_numbers_negative():
|
31
|
-
# Working with negative numbers
|
32
|
-
result = add_numbers(-5, 3)
|
33
|
-
assert result == -2
|
34
|
-
|
35
|
-
def test_add_numbers_zero():
|
36
|
-
# Working with zeros
|
37
|
-
result = add_numbers(0, 0)
|
38
|
-
assert result == 0
|
39
|
-
```
|
40
|
-
|
41
|
-
### 2. Integration Testing
|
42
|
-
|
43
|
-
Testing commands with real dependencies or their mocks.
|
44
|
-
|
45
|
-
```python
|
46
|
-
import pytest
|
47
|
-
from unittest.mock import MagicMock, patch
|
48
|
-
from myapp.commands.user_commands import get_user_data
|
49
|
-
|
50
|
-
@pytest.fixture
|
51
|
-
def mock_db():
|
52
|
-
"""Fixture for creating database mock."""
|
53
|
-
mock = MagicMock()
|
54
|
-
mock.users.find_one.return_value = {
|
55
|
-
"id": "user123",
|
56
|
-
"name": "Test User",
|
57
|
-
"email": "test@example.com",
|
58
|
-
"created_at": "2023-01-01T00:00:00Z"
|
59
|
-
}
|
60
|
-
return mock
|
61
|
-
|
62
|
-
@patch("myapp.commands.user_commands.get_database")
|
63
|
-
def test_get_user_data(get_database_mock, mock_db):
|
64
|
-
# Setup mock
|
65
|
-
get_database_mock.return_value = mock_db
|
66
|
-
|
67
|
-
# Call command
|
68
|
-
result = get_user_data("user123")
|
69
|
-
|
70
|
-
# Assertions
|
71
|
-
assert result["id"] == "user123"
|
72
|
-
assert result["name"] == "Test User"
|
73
|
-
assert "email" in result
|
74
|
-
|
75
|
-
# Verify DB call with correct parameters
|
76
|
-
mock_db.users.find_one.assert_called_once_with({"id": "user123"})
|
77
|
-
```
|
78
|
-
|
79
|
-
### 3. Testing Through Command Registry
|
80
|
-
|
81
|
-
Testing commands through Command Registry interface.
|
82
|
-
|
83
|
-
```python
|
84
|
-
import pytest
|
85
|
-
from command_registry import CommandRegistry
|
86
|
-
from command_registry.dispatchers import CommandDispatcher
|
87
|
-
from myapp.commands.math_commands import add_numbers, subtract_numbers
|
88
|
-
|
89
|
-
@pytest.fixture
|
90
|
-
def registry():
|
91
|
-
"""Fixture for creating CommandRegistry with registered commands."""
|
92
|
-
registry = CommandRegistry(CommandDispatcher())
|
93
|
-
registry.register_command("add", add_numbers)
|
94
|
-
registry.register_command("subtract", subtract_numbers)
|
95
|
-
return registry
|
96
|
-
|
97
|
-
def test_registry_add_command(registry):
|
98
|
-
# Execute command through registry
|
99
|
-
result = registry.execute("add", {"a": 10, "b": 5})
|
100
|
-
assert result == 15
|
101
|
-
|
102
|
-
def test_registry_subtract_command(registry):
|
103
|
-
# Execute command through registry
|
104
|
-
result = registry.execute("subtract", {"a": 10, "b": 5})
|
105
|
-
assert result == 5
|
106
|
-
|
107
|
-
def test_command_not_found(registry):
|
108
|
-
# Check handling of non-existent command
|
109
|
-
with pytest.raises(ValueError, match="Command 'multiply' not found"):
|
110
|
-
registry.execute("multiply", {"a": 10, "b": 5})
|
111
|
-
```
|
112
|
-
|
113
|
-
### 4. E2E Testing Through API
|
114
|
-
|
115
|
-
Testing commands through external interfaces (REST, JSON-RPC, etc.).
|
116
|
-
|
117
|
-
```python
|
118
|
-
import pytest
|
119
|
-
from fastapi.testclient import TestClient
|
120
|
-
from myapp.main import app # FastAPI application with registered commands
|
121
|
-
|
122
|
-
client = TestClient(app)
|
123
|
-
|
124
|
-
def test_add_numbers_api():
|
125
|
-
response = client.post(
|
126
|
-
"/api/commands/add",
|
127
|
-
json={"a": 10, "b": 5}
|
128
|
-
)
|
129
|
-
assert response.status_code == 200
|
130
|
-
assert response.json() == {"result": 15}
|
131
|
-
|
132
|
-
def test_invalid_params_api():
|
133
|
-
response = client.post(
|
134
|
-
"/api/commands/add",
|
135
|
-
json={"a": "not_a_number", "b": 5}
|
136
|
-
)
|
137
|
-
assert response.status_code == 400
|
138
|
-
assert "error" in response.json()
|
139
|
-
```
|
140
|
-
|
141
|
-
## Testing Using Parameterization
|
142
|
-
|
143
|
-
Parameterization allows testing multiple scenarios with different inputs and expectations.
|
144
|
-
|
145
|
-
```python
|
146
|
-
import pytest
|
147
|
-
from myapp.commands.math_commands import calculate_total
|
148
|
-
|
149
|
-
@pytest.mark.parametrize("prices, discount, expected", [
|
150
|
-
([10, 20, 30], 0, 60), # No discount
|
151
|
-
([10, 20, 30], 10, 54), # 10% discount
|
152
|
-
([100], 50, 50), # 50% discount
|
153
|
-
([], 10, 0), # Empty list
|
154
|
-
])
|
155
|
-
def test_calculate_total(prices, discount, expected):
|
156
|
-
result = calculate_total(prices, discount)
|
157
|
-
assert result == expected
|
158
|
-
|
159
|
-
@pytest.mark.parametrize("invalid_discount", [-10, 110, "invalid"])
|
160
|
-
def test_calculate_total_invalid_discount(invalid_discount):
|
161
|
-
with pytest.raises(ValueError):
|
162
|
-
calculate_total([10, 20], invalid_discount)
|
163
|
-
```
|
164
|
-
|
165
|
-
## Testing Asynchronous Commands
|
166
|
-
|
167
|
-
Use pytest-asyncio for testing asynchronous commands.
|
168
|
-
|
169
|
-
```python
|
170
|
-
import pytest
|
171
|
-
import asyncio
|
172
|
-
from unittest.mock import AsyncMock, patch
|
173
|
-
from myapp.commands.async_commands import fetch_user_data
|
174
|
-
|
175
|
-
@pytest.mark.asyncio
|
176
|
-
@patch("myapp.commands.async_commands.get_async_database")
|
177
|
-
async def test_fetch_user_data(mock_get_db):
|
178
|
-
# Create async mock
|
179
|
-
mock_db = AsyncMock()
|
180
|
-
mock_db.users.find_one.return_value = {"id": "user123", "name": "Test User"}
|
181
|
-
mock_get_db.return_value = mock_db
|
182
|
-
|
183
|
-
# Call async command
|
184
|
-
result = await fetch_user_data("user123")
|
185
|
-
|
186
|
-
# Check result
|
187
|
-
assert result["id"] == "user123"
|
188
|
-
assert result["name"] == "Test User"
|
189
|
-
|
190
|
-
# Verify mock was called with correct parameters
|
191
|
-
mock_db.users.find_one.assert_called_once_with({"id": "user123"})
|
192
|
-
```
|
193
|
-
|
194
|
-
## Testing Error Handling
|
195
|
-
|
196
|
-
```python
|
197
|
-
import pytest
|
198
|
-
from myapp.commands.user_commands import get_user_data
|
199
|
-
from myapp.exceptions import UserNotFoundError
|
200
|
-
|
201
|
-
@patch("myapp.commands.user_commands.get_database")
|
202
|
-
def test_get_user_data_not_found(mock_get_db):
|
203
|
-
# Configure mock to return None (user not found)
|
204
|
-
db_mock = MagicMock()
|
205
|
-
db_mock.users.find_one.return_value = None
|
206
|
-
mock_get_db.return_value = db_mock
|
207
|
-
|
208
|
-
# Check that command raises expected exception
|
209
|
-
with pytest.raises(UserNotFoundError, match="User with id 'unknown_user' not found"):
|
210
|
-
get_user_data("unknown_user")
|
211
|
-
```
|
212
|
-
|
213
|
-
## Testing Parameter Validation
|
214
|
-
|
215
|
-
```python
|
216
|
-
import pytest
|
217
|
-
from myapp.commands.product_commands import update_product_price
|
218
|
-
|
219
|
-
def test_update_product_price_negative():
|
220
|
-
# Check for negative price
|
221
|
-
with pytest.raises(ValueError, match="Price cannot be negative"):
|
222
|
-
update_product_price("product123", -10.0)
|
223
|
-
|
224
|
-
def test_update_product_price_invalid_id():
|
225
|
-
# Check for empty product ID
|
226
|
-
with pytest.raises(ValueError, match="Product ID cannot be empty"):
|
227
|
-
update_product_price("", 10.0)
|
228
|
-
```
|
229
|
-
|
230
|
-
## Using Fixtures for Common Cases
|
231
|
-
|
232
|
-
```python
|
233
|
-
import pytest
|
234
|
-
from command_registry import CommandRegistry
|
235
|
-
from command_registry.dispatchers import CommandDispatcher
|
236
|
-
import myapp.commands as commands
|
237
|
-
|
238
|
-
@pytest.fixture
|
239
|
-
def registry():
|
240
|
-
"""Creates CommandRegistry with all registered commands."""
|
241
|
-
registry = CommandRegistry(CommandDispatcher())
|
242
|
-
registry.scan_module(commands)
|
243
|
-
return registry
|
244
|
-
|
245
|
-
@pytest.fixture
|
246
|
-
def mock_database():
|
247
|
-
"""Creates database mock with test data."""
|
248
|
-
db = MagicMock()
|
249
|
-
db.users.find_one.return_value = {"id": "user1", "name": "Test User"}
|
250
|
-
db.products.find.return_value = [
|
251
|
-
{"id": "product1", "name": "Test Product", "price": 10.0},
|
252
|
-
{"id": "product2", "name": "Another Product", "price": 20.0}
|
253
|
-
]
|
254
|
-
return db
|
255
|
-
```
|