API Testing:
- docs/guides/API_TESTING_GUIDE.md - полное руководство по API тестированию
* Использование Postman коллекции
* Newman CLI интеграция
* REST Client примеры
* Pytest примеры с fixtures
- docs/reports/API_EMPLOYEES_COVERAGE.md - анализ покрытия эндпоинтов
* Покрытие расширено с 23% до ~70%
* Список протестированных и непокрытых эндпоинтов
Database Optimization:
- backend/docs/reports/DB_QUERIES_ANALYSIS.md - детальный анализ запросов к БД
* 8 ViewSet'ов проанализированы
* Найдены критические N+1 проблемы:
- SkillViewSet.merge() делает 2N запросов в цикле
- GroupViewSet.retrieve не использует prefetch_related
- RegisterAPIView дважды проверяет email
* Предложены оптимизации с raw SQL
* Рейтинг текущего состояния: 4/5 звезд
11 KiB
11 KiB
Руководство по тестированию API
Содержание
- Инструменты для тестирования
- Postman
- REST Client (VS Code)
- Pytest (автоматизированные тесты)
- cURL примеры
Инструменты для тестирования
Postman
Импорт коллекции:
- Откройте Postman
- Нажмите
Import - Выберите файл
EUSRR_API.postman_collection.jsonиз корня проекта - Коллекция будет импортирована со всеми запросами
Настройка переменных:
Postman коллекция использует переменные:
base_url- базовый URL API (по умолчаниюhttp://localhost:8000)access_token- JWT токен (автоматически сохраняется после Login)refresh_token- токен обновления
Порядок работы:
- Запустите запрос Authentication > Login
- Токены автоматически сохранятся в переменные
- Все остальные запросы будут использовать
access_tokenавтоматически - При истечении токена используйте Authentication > Refresh Token
REST Client (VS Code)
Установка:
# В VS Code установите расширение
REST Client by Huachao Mao
Использование:
- Откройте файл
api_tests.httpиз корня проекта - Выполните запрос Login (кликните "Send Request" над запросом)
- Скопируйте полученный
accessтокен - Замените
@accessToken = your_access_token_hereна реальный токен - Теперь можете выполнять любые запросы
Преимущества:
- Работает прямо в VS Code
- Легко редактировать и сохранять запросы
- Поддержка переменных
- История запросов
Pytest (автоматизированные тесты)
Запуск тестов API:
# В Docker контейнере
docker-compose exec web pytest tests/api/
# Или локально через venv
.venv/Scripts/python -m pytest tests/api/
# Запуск конкретного теста
docker-compose exec web pytest tests/api/v1/test_employees.py
# С выводом покрытия
docker-compose exec web pytest tests/api/ --cov=api --cov-report=html
Пример написания теста:
# tests/api/v1/test_employees.py
import pytest
from django.urls import reverse
from rest_framework import status
from rest_framework.test import APIClient
@pytest.mark.django_db
class TestEmployeeAPI:
def test_list_employees_requires_auth(self):
"""Тест: список сотрудников требует авторизации"""
client = APIClient()
url = reverse('api:v1:employees-list')
response = client.get(url)
assert response.status_code == status.HTTP_401_UNAUTHORIZED
def test_list_employees_with_auth(self, authenticated_client, user):
"""Тест: авторизованный пользователь может получить список"""
url = reverse('api:v1:employees-list')
response = authenticated_client.get(url)
assert response.status_code == status.HTTP_200_OK
assert 'results' in response.data
def test_get_current_user(self, authenticated_client, user):
"""Тест: получение информации о текущем пользователе"""
url = reverse('api:v1:employees-me')
response = authenticated_client.get(url)
assert response.status_code == status.HTTP_200_OK
assert response.data['email'] == user.email
Fixtures для тестов:
# tests/conftest.py
import pytest
from rest_framework.test import APIClient
from rest_framework_simplejwt.tokens import RefreshToken
from employees.models import Employee
@pytest.fixture
def api_client():
"""Базовый API клиент"""
return APIClient()
@pytest.fixture
def user(db):
"""Создание тестового пользователя"""
return Employee.objects.create_user(
email='test@example.com',
password='testpass123',
first_name='Test',
last_name='User'
)
@pytest.fixture
def authenticated_client(api_client, user):
"""API клиент с авторизацией"""
refresh = RefreshToken.for_user(user)
api_client.credentials(
HTTP_AUTHORIZATION=f'Bearer {refresh.access_token}'
)
return api_client
cURL примеры
Получение токена
curl -X POST http://localhost:8000/api/auth/token/ \
-H "Content-Type: application/json" \
-d '{
"username": "admin@example.com",
"password": "password"
}'
Список сотрудников
TOKEN="your_access_token_here"
curl -X GET http://localhost:8000/api/v1/employees/ \
-H "Authorization: Bearer $TOKEN"
Создание поста
TOKEN="your_access_token_here"
curl -X POST http://localhost:8000/api/v1/posts/ \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"content": "Новый пост через cURL!"
}'
Отправка сообщения
TOKEN="your_access_token_here"
curl -X POST http://localhost:8000/api/v1/communications/messages/ \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"chat": 1,
"content": "Привет из cURL!"
}'
Типичные сценарии тестирования
1. Проверка аутентификации
# 1. Получить токен
# 2. Проверить доступ к защищенному endpoint
# 3. Проверить, что без токена доступ запрещен
2. CRUD операции
# Create - создать ресурс
# Read - получить список и конкретный ресурс
# Update - обновить ресурс (PUT/PATCH)
# Delete - удалить ресурс
3. Пагинация
GET /api/v1/employees/?page=1
GET /api/v1/employees/?page=2&page_size=20
4. Фильтрация
GET /api/v1/employees/?search=Иванов
GET /api/v1/requests/?status=pending
GET /api/v1/documents/?document_type=report
5. Сортировка
GET /api/v1/employees/?ordering=last_name
GET /api/v1/posts/?ordering=-created_at
Проверка WebSocket соединений
Использование wscat
# Установка wscat
npm install -g wscat
# Подключение к WebSocket
wscat -c "ws://localhost:8000/ws/chat/1/?token=YOUR_ACCESS_TOKEN"
# Отправка сообщения
{"type": "message", "content": "Hello!"}
Использование Python
import websocket
import json
def on_message(ws, message):
print(f"Received: {message}")
def on_error(ws, error):
print(f"Error: {error}")
def on_open(ws):
print("Connection opened")
# Отправить сообщение
ws.send(json.dumps({
"type": "message",
"content": "Hello from Python!"
}))
token = "YOUR_ACCESS_TOKEN"
ws_url = f"ws://localhost:8000/ws/chat/1/?token={token}"
ws = websocket.WebSocketApp(
ws_url,
on_message=on_message,
on_error=on_error,
on_open=on_open
)
ws.run_forever()
Тестирование производительности
Apache Bench (ab)
# Установка (обычно входит в Apache)
# На Windows: скачать с https://www.apachelounge.com/
# Тест производительности
ab -n 1000 -c 10 \
-H "Authorization: Bearer YOUR_TOKEN" \
http://localhost:8000/api/v1/employees/
Locust
# locustfile.py
from locust import HttpUser, task, between
class EUSRRUser(HttpUser):
wait_time = between(1, 3)
token = None
def on_start(self):
"""Логин при старте"""
response = self.client.post("/api/auth/token/", json={
"username": "admin@example.com",
"password": "password"
})
self.token = response.json()["access"]
@task(3)
def list_employees(self):
self.client.get(
"/api/v1/employees/",
headers={"Authorization": f"Bearer {self.token}"}
)
@task(2)
def list_posts(self):
self.client.get(
"/api/v1/posts/",
headers={"Authorization": f"Bearer {self.token}"}
)
@task(1)
def create_post(self):
self.client.post(
"/api/v1/posts/",
json={"content": "Load test post"},
headers={"Authorization": f"Bearer {self.token}"}
)
Запуск:
# Установка
pip install locust
# Запуск
locust -f locustfile.py --host=http://localhost:8000
# Откройте http://localhost:8089 для веб-интерфейса
Мониторинг API
Django Debug Toolbar
Уже установлен в проекте. Доступен в режиме DEBUG=True:
- Показывает SQL запросы
- Время выполнения
- Используемые шаблоны
- Кеш операции
Логирование API запросов
# settings.py
LOGGING = {
'loggers': {
'api': {
'handlers': ['console'],
'level': 'DEBUG',
},
},
}
Troubleshooting
Ошибка 401 Unauthorized
- Проверьте, что токен актуален
- Токены истекают через определенное время (см.
SIMPLE_JWTнастройки) - Используйте Refresh Token для получения нового Access Token
Ошибка 403 Forbidden
- Пользователь авторизован, но не имеет прав
- Проверьте permissions в viewsets
- Проверьте группы и роли пользователя
Ошибка 404 Not Found
- Проверьте URL endpoint
- Убедитесь, что ресурс с таким ID существует
Ошибка 500 Internal Server Error
- Проверьте логи сервера:
docker-compose logs web - Проверьте валидность отправляемых данных
- Проверьте serializers и validators