JavaRush /Курсы /Модуль 3: Django /Практическое создание тестов для существующих эндпоинтов

Практическое создание тестов для существующих эндпоинтов

Модуль 3: Django
22 уровень , 8 лекция
Открыта

Сегодня мы возьмем всё, что узнали о тестировании API, и применим эти знания на практике. В центре нашего внимания окажутся тесты для существующих эндпоинтов нашего проекта. Мы будем писать тесты для CRUD-операций, проверять авторизацию и разрешения, а также отлавливать потенциальные баги.

Создаём тесты для CRUD-операций

Наша цель — протестировать базовые операции CRUD для начального API, который мы разрабатывали ранее. До этого момента, у нас уже есть модель Book с полями title и author, а также эндпоинты для этого ресурса.

Вспомнить: эндпоинты для модели Book

  • GET /api/books/ — получить список всех книг;
  • POST /api/books/ — создать новую книгу;
  • GET /api/books/<id>/</id> — получить информацию о книге по её ID;
  • PUT /api/books/<id>/</id> — обновить информацию о книге;
  • DELETE /api/books/<id>/</id> — удалить книгу.

Начальная подготовка Создайте файл test_views.py в директории с тестами вашего приложения (например, books/tests/). После этого можно приступать.

Тесты для списка книг (GET)

Сначала мы проверим, что наш эндпоинт /api/books/ возвращает корректный результат.

import pytest
from django.urls import reverse
from rest_framework import status
from rest_framework.test import APIClient
from books.models import Book

@pytest.mark.django_db
def test_get_books_list():
    # Создаём тестовые данные
    Book.objects.create(title="Django for Beginners", author="William S. Vincent")
    Book.objects.create(title="Python Crash Course", author="Eric Matthes")

    # Создаем клиент для тестов
    client = APIClient()

    # Выполняем GET-запрос
    response = client.get(reverse('books-list'))

    # Проверяем статус ответа
    assert response.status_code == status.HTTP_200_OK

    # Убеждаемся, что возвращённые данные корректны
    data = response.json()
    assert len(data) == 2
    assert data[0]['title'] == "Django for Beginners"
    assert data[1]['title'] == "Python Crash Course"

Здесь мы проверяем, что:

  • Наш эндпоинт возвращает успешный ответ с кодом 200;
  • Содержимое ответа соответствует нашим тестовым данным.

Тесты для создания книги (POST)

Теперь давайте протестируем, что эндпоинт для создания книги работает как положено.

@pytest.mark.django_db
def test_create_book():
    # Создаем клиент для тестов
    client = APIClient()

    # Создаем запрос на добавление книги
    payload = {
        "title": "Two Scoops of Django",
        "author": "Audrey Roy Greenfeld"
    }
    response = client.post(reverse('books-list'), payload, format='json')

    # Проверяем статус ответа
    assert response.status_code == status.HTTP_201_CREATED

    # Убеждаемся, что книга создалась в базе данных
    book = Book.objects.get(id=response.data['id'])
    assert book.title == payload['title']
    assert book.author == payload['author']

Чистый, простой тест для добавления книги. Мы:

  1. Проверяем, что статус ответа — 201 CREATED;
  2. Проверяем, что объект действительно сохранился в базе данных с указанными полями.

Тесты для получения книги (GET /<id>/)</id>

Следующий шаг — проверить, что мы можем получить конкретный объект по его ID.

@pytest.mark.django_db
def test_get_book_detail():
    # Создаём тестовые данные
    book = Book.objects.create(title="Effective Python", author="Brett Slatkin")

    # Создаем клиент для тестов
    client = APIClient()

    # Выполняем GET-запрос
    response = client.get(reverse('books-detail', kwargs={'pk': book.id}))

    # Проверяем статус ответа
    assert response.status_code == status.HTTP_200_OK

    # Убеждаемся, что данные ответа совпадают с данными книги
    data = response.json()
    assert data['title'] == book.title
    assert data['author'] == book.author

Максимально подробно проверяем, что возвращаются именно те данные, которые связаны с конкретным ID.

Тесты для обновления книги (PUT)

Теперь проверим, как работает обновление книги.

@pytest.mark.django_db
def test_update_book():
    # Создаём тестовые данные
    book = Book.objects.create(title="Python Tricks", author="Dan Bader")

    # Создаем клиент для тестов
    client = APIClient()

    # Данные для обновления
    payload = {
        "title": "Python Tricks Updated",
        "author": "Dan Bader"
    }
    response = client.put(reverse('books-detail', kwargs={'pk': book.id}), payload, format='json')

    # Проверяем статус ответа
    assert response.status_code == status.HTTP_200_OK

    # Проверяем, что книга обновилась
    book.refresh_from_db()
    assert book.title == payload['title']
    assert book.author == payload['author']

Мы здесь используем метод refresh_from_db, чтобы обновить объект из базы данных.

Тесты для удаления книги (DELETE)

Наконец, протестируем удаление объекта.

@pytest.mark.django_db
def test_delete_book():
    # Создаём тестовые данные
    book = Book.objects.create(title="Learn Python the Hard Way", author="Zed Shaw")

    # Создаем клиент для тестов
    client = APIClient()

    # Удаляем книгу
    response = client.delete(reverse('books-detail', kwargs={'pk': book.id}))

    # Проверяем статус ответа
    assert response.status_code == status.HTTP_204_NO_CONTENT

    # Убеждаемся, что книга удалена из базы данных
    assert not Book.objects.filter(id=book.id).exists()

Книга удаляется успешно, а мы проверяем, что она больше не существует в базе данных.

Анализ и исправление ошибок в тестах

Ошибки во время тестирования — это нормально. Если вы столкнулись с багом или тест не проходит, надо действовать последовательно:

  1. Проверьте сообщение об ошибке. Оно часто подскажет, где именно есть проблема.
  2. Используйте print или breakpoints для отладки теста.
  3. Запускайте тесты изолированно, чтобы определить, какой именно из них вызывает проблему (pytest -k test_name).

Предположим, что вы забыли зарегистрировать ваш эндпоинт в urls.py. Тесты сразу покажут ошибку NoReverseMatch, что поможет вам моментально исправить проблему.

Практика: написание тестов

Попробуйте написать тесты для следующих случаев:

  1. Проверка, что при отправке недопустимых данных (title или author пустые) наш API возвращает ошибку валидации с кодом 400 BAD REQUEST.
  2. Тест для проверки, что пагинированный эндпоинт возвращает заданное количество объектов на странице.
  3. Проверьте, что у неавторизованного пользователя нет доступа к созданию книги (если у вас включён такой сценарий).

На этом всё! Вы написали тесты для CRUD-операций и научились анализировать результаты тестирования. Благодаря такому подходу вы теперь уверены, что ваши API эндпоинты работают корректно, а изменения в коде не ломают существующий функционал.

1
Задача
Модуль 3: Django, 22 уровень, 8 лекция
Недоступна
Тестирование сложного сценария
Тестирование сложного сценария
1
Задача
Модуль 3: Django, 22 уровень, 8 лекция
Недоступна
Комбинированное тестирование CRUD
Комбинированное тестирование CRUD
Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ