← Назад к вопросам

Тестировал ли API на Django

2.0 Middle🔥 121 комментариев
#Django

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Тестирование 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.