Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Тестирование API на Django: Практический Опыт
Да, тестирование API — это критически важная часть моей работы. Я активно использую Django Test Client и инструменты для автоматизированного тестирования REST API.
Основной Инструмент: Django Test Client
Django предоставляет встроенный Test Client для тестирования HTTP запросов без необходимости запускать реальный сервер:
from django.test import TestCase, Client
from django.contrib.auth.models import User
class UserAPITestCase(TestCase):
def setUp(self):
self.client = Client()
self.user = User.objects.create_user(
username="testuser",
password="testpass123"
)
def test_create_user(self):
response = self.client.post("/api/v1/users/", {
"username": "newuser",
"email": "new@example.com",
"password": "securepass123"
})
self.assertEqual(response.status_code, 201)
self.assertEqual(response.json()["username"], "newuser")
Тестирование с Authentication
Часто требуется тестировать защищённые endpoints:
from rest_framework.test import APITestCase
from rest_framework.authtoken.models import Token
class ProtectedAPITestCase(APITestCase):
def setUp(self):
self.user = User.objects.create_user(
username="john",
password="pass123"
)
self.token = Token.objects.create(user=self.user)
def test_protected_endpoint(self):
# Без токена — доступ запрещён
response = self.client.get("/api/v1/profile/")
self.assertEqual(response.status_code, 401)
# С токеном — доступ разрешён
self.client.credentials(HTTP_AUTHORIZATION="Token " + self.token.key)
response = self.client.get("/api/v1/profile/")
self.assertEqual(response.status_code, 200)
self.assertEqual(response.json()["username"], "john")
Использование Django REST Framework Test Client
Для более удобного тестирования REST API используется APIClient:
from rest_framework.test import APIClient
class OrderAPITestCase(TestCase):
def setUp(self):
self.client = APIClient()
self.user = User.objects.create_user(
username="buyer",
password="pass123"
)
def test_create_order(self):
# Логинимся
self.client.force_authenticate(user=self.user)
# Отправляем JSON
response = self.client.post("/api/v1/orders/", {
"product_id": 1,
"quantity": 5
}, format="json")
self.assertEqual(response.status_code, 201)
self.assertEqual(response.data["status"], "pending")
Параметризованное Тестирование
Для тестирования множества сценариев я использую параметризацию:
from parameterized import parameterized
class APIStatusCodesTestCase(TestCase):
@parameterized.expand([
(200, "get", "/api/v1/users/"),
(404, "get", "/api/v1/nonexistent/"),
(400, "post", "/api/v1/users/", {}), # Пустые данные
(405, "delete", "/api/v1/users/"),
])
def test_status_codes(self, expected_status, method, url, data=None):
if method == "get":
response = self.client.get(url)
elif method == "post":
response = self.client.post(url, data, content_type="application/json")
elif method == "delete":
response = self.client.delete(url)
self.assertEqual(response.status_code, expected_status)
Тестирование с Фикстурами и Mock
from unittest.mock import patch, MagicMock
from django.test import TestCase
class ExternalAPIIntegrationTestCase(TestCase):
def setUp(self):
self.client = Client()
@patch("myapp.services.payment_service.charge_card")
def test_payment_with_mock(self, mock_charge):
# Настраиваем mock
mock_charge.return_value = {"status": "success", "transaction_id": "txn_123"}
# Тестируем
response = self.client.post("/api/v1/payments/", {
"amount": 100.00,
"card_token": "tok_visa"
})
self.assertEqual(response.status_code, 200)
mock_charge.assert_called_once()
Использование Django Test Fixtures
class APIWithFixturesTestCase(TestCase):
fixtures = ["users.json", "products.json"] # Предзаполненные данные
def test_get_products(self):
response = self.client.get("/api/v1/products/")
self.assertEqual(response.status_code, 200)
self.assertGreater(len(response.json()), 0)
Инструменты для Тестирования
Pytest + pytest-django — модернизированная альтернатива unittest:
import pytest
from django.test import Client
@pytest.mark.django_db
class TestUserAPI:
def test_create_user(self):
client = Client()
response = client.post("/api/v1/users/", {
"username": "john",
"password": "pass123"
})
assert response.status_code == 201
Критические Аспекты при Тестировании API
- Изоляция тестов — используй
@transactionTestCaseдля тестов с коммитами - Тестирование ошибок — проверяй 400, 403, 404, 500 статусы
- Валидация данных — тестируй граничные случаи
- Аутентификация и авторизация — критически важно
- Тестирование сложных операций — используй
@transaction.atomic()для чистоты
Заключение
Тестирование API на Django — это стандартная практика. Я регулярно использую Django Test Client, APIClient, параметризованные тесты и мокирование для обеспечения качества и надёжности API.