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 ендпоінти працюють коректно, а зміни в коді не ламають існуючий функціонал.

Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ