Skip to main content
Glama
test_endpoints.py7.53 kB
""" Тесты для проверки эндпоинтов MCP сервера. """ import json from collections.abc import AsyncGenerator from typing import Dict import pytest import websockets from fastapi.testclient import TestClient from httpx import AsyncClient from websockets.client import WebSocketClientProtocol from app.main import app @pytest.fixture def client() -> TestClient: """Фикстура для синхронного клиента FastAPI.""" return TestClient(app) @pytest.fixture async def async_client() -> AsyncGenerator[AsyncClient, None]: """Фикстура для асинхронного клиента FastAPI.""" async with AsyncClient(app=app, base_url="http://test") as client: yield client # REST API тесты def test_health_check(client: TestClient) -> None: """Тест эндпоинта проверки здоровья.""" response = client.get("/health") assert response.status_code == 200 assert response.json() == {"status": "healthy"} def test_list_tools(client: TestClient) -> None: """Тест получения списка инструментов.""" response = client.get("/tools") assert response.status_code == 200 tools = response.json()["tools"] assert isinstance(tools, list) assert len(tools) > 0 assert all( isinstance(tool, dict) and "name" in tool and "description" in tool for tool in tools ) def test_execute_file_operations_tool(client: TestClient) -> None: """Тест выполнения инструмента file_operations.""" response = client.post( "/tools/file_operations", json={ "operation": "list", "path": "app", }, ) assert response.status_code == 200 result = response.json() assert "success" in result assert result["success"] is True assert "result" in result assert "content" in result["result"] def test_execute_weather_tool(client: TestClient) -> None: """Тест выполнения инструмента weather.""" response = client.post( "/tools/weather", json={ "latitude": 40.7128, "longitude": -74.0060, }, ) assert response.status_code == 200 result = response.json() assert "success" in result assert "result" in result assert "content" in result["result"] # GraphQL тесты def test_graphql_get_tools(client: TestClient) -> None: """Тест GraphQL запроса на получение инструментов.""" query = """ query { getTools { name description inputSchema } } """ response = client.post("/graphql", json={"query": query}) assert response.status_code == 200 data = response.json() assert "data" in data assert "getTools" in data["data"] tools = data["data"]["getTools"] assert isinstance(tools, list) assert len(tools) > 0 def test_graphql_execute_tool(client: TestClient) -> None: """Тест GraphQL мутации для выполнения инструмента.""" mutation = """ mutation { executeTool( input: { name: "weather", parameters: { latitude: 40.7128, longitude: -74.0060 } } ) { content { type text } is_error } } """ response = client.post("/graphql", json={"query": mutation}) assert response.status_code == 200 data = response.json() assert "data" in data assert "executeTool" in data["data"] # WebSocket тесты @pytest.mark.asyncio async def test_websocket_connection(): """Тест WebSocket соединения.""" async with websockets.connect("ws://localhost:8000/ws") as websocket: # Тест выполнения инструмента через WebSocket await test_websocket_execute_tool(websocket) async def test_websocket_execute_tool(websocket: WebSocketClientProtocol): """Тест выполнения инструмента через WebSocket.""" message = { "type": "execute_tool", "tool": "weather", "parameters": { "latitude": 40.7128, "longitude": -74.0060, }, } await websocket.send(json.dumps(message)) response = await websocket.recv() data = json.loads(response) assert isinstance(data, dict) assert "content" in data # Тесты ошибок def test_invalid_tool_name(client: TestClient) -> None: """Тест запроса к несуществующему инструменту.""" response = client.post( "/tools/nonexistent_tool", json={ "operation": "test", }, ) assert response.status_code == 404 def test_invalid_tool_parameters(client: TestClient) -> None: """Тест запроса с неверными параметрами.""" response = client.post( "/tools/weather", json={ "invalid_param": "test", }, ) assert response.status_code in (400, 422) # Validation error def test_graphql_invalid_query(client: TestClient) -> None: """Тест невалидного GraphQL запроса.""" query = """ query { invalidField { name } } """ response = client.post("/graphql", json={"query": query}) assert response.status_code == 200 data = response.json() assert "errors" in data # Интеграционные тесты @pytest.mark.asyncio async def test_tool_execution_flow(async_client: AsyncClient) -> None: """ Интеграционный тест потока выполнения инструмента: 1. Получение списка инструментов 2. Выполнение инструмента 3. Проверка результата """ # 1. Получаем список инструментов response = await async_client.get("/tools") assert response.status_code == 200 tools = response.json()["tools"] assert len(tools) > 0 # 2. Выбираем инструмент weather weather_tool = next( (tool for tool in tools if tool["name"] == "weather"), None, ) assert weather_tool is not None # 3. Выполняем инструмент response = await async_client.post( "/tools/weather", json={ "latitude": 40.7128, "longitude": -74.0060, }, ) assert response.status_code == 200 result = response.json() assert result["success"] is True @pytest.mark.asyncio async def test_multiple_concurrent_requests(async_client: AsyncClient) -> None: """Тест одновременного выполнения нескольких запросов.""" import asyncio async def make_request() -> Dict: response = await async_client.get("/tools") return response.json() # Выполняем 10 одновременных запросов tasks = [make_request() for _ in range(10)] results = await asyncio.gather(*tasks) # Проверяем, что все запросы выполнились успешно assert len(results) == 10 assert all("tools" in result for result in results)

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/eagurin/myaiserv'

If you have feedback or need assistance with the MCP directory API, please join our Discord server