JavaRush /Курси /Модуль 4: FastAPI /Приклад написання повного набору тестів для API

Приклад написання повного набору тестів для API

Модуль 4: FastAPI
Рівень 5 , Лекція 9
Відкрита

Сьогодні ми напишемо повний набір тестів для FastAPI-додатка. Ми пройдемося по всіх ключових можливостях API і переконаємося, що наш додаток працює як годинник. Для цього ми:

  • Навчимося організовувати тести так, щоб вони були структурованими;
  • Покриємо основні кейси, включаючи захищені ендпоінти, обробку помилок і перевірку бізнес-логіки;
  • Розберемося, як писати тести, які не тільки перевіряють працездатність додатка, але й допомагають знайти кути, про які ми могли не подумати.

Приклад додатка: база даних користувачів

Для тестування візьмемо невеликий додаток, який ми розробляли раніше — базу даних користувачів з CRUD-операціями. Ось його основні ендпоінти:

  • GET /users/ — отримання списку користувачів.
  • GET /users/{user_id} — отримання даних конкретного користувача.
  • POST /users/ — створення нового користувача.
  • PUT /users/{user_id} — оновлення даних користувача.
  • DELETE /users/{user_id} — видалення користувача.

Крім того, додаток підтримує:

  • Валідацію даних через Pydantic;
  • Аутентифікацію через JWT;
  • Обробку кастомних помилок (наприклад, якщо користувача не знайдено).

Перед тестуванням переконайтеся, що структура вашого проєкту виглядає приблизно так:

project/
├── app/
│   ├── main.py
│   ├── models.py
│   ├── schemas.py
│   ├── database.py
│   ├── routers/
│   │   └── users.py
├── tests/
│   └── test_users.py

План тестування

Весь процес тестування розіб'ємо на наступні етапи:

  1. Тестування публічних ендпоінтів (GET-запити).
  2. Тестування захищених ендпоінтів (POST, PUT, DELETE).
  3. Перевірка обробки помилок.
  4. Робота з фікстурами для прискорення написання тестів.
  5. Перевірка покриття коду.

Тестування публічних ендпоінтів

Спочатку протестуємо, як працює отримання даних через GET /users/ і GET /users/{user_id}. Для цього ми будемо використовувати вбудований TestClient з FastAPI.

Приклад тесту для отримання списку користувачів


from fastapi.testclient import TestClient
from app.main import app

client = TestClient(app)

def test_get_all_users():
    response = client.get("/users/")
    assert response.status_code == 200
    assert isinstance(response.json(), list)  # Відповідь має бути списком

Приклад тесту для отримання конкретного користувача


def test_get_user_by_id():
    user_id = 1
    response = client.get(f"/users/{user_id}")
    assert response.status_code == 200
    data = response.json()
    assert data["id"] == user_id
    assert "email" in data  # Перевіряємо наявність очікуваних полів

Тестування захищених ендпоінтів

Оскільки деякі ендпоінти вимагають аутентифікацію, нам потрібно передавати коректний JWT-токен. У реальних додатках ви, швидше за все, будете тестувати не тільки коректні токени, але й сценарії, коли вони відсутні або невалідні.

Фікстура для створення токена


import jwt
from datetime import datetime, timedelta

SECRET_KEY = "supersecretkey"

def get_test_token(user_id: int):
    payload = {
        "sub": user_id,
        "exp": datetime.utcnow() + timedelta(minutes=15)
    }
    return jwt.encode(payload, SECRET_KEY, algorithm="HS256")

Приклад тесту для створення користувача


def test_create_user():
    token = get_test_token(user_id=1)
    headers = {"Authorization": f"Bearer {token}"}
    payload = {
        "email": "testuser@example.com",
        "name": "Test User",
        "age": 25
    }
    response = client.post("/users/", json=payload, headers=headers)
    assert response.status_code == 201
    data = response.json()
    assert data["email"] == payload["email"]

Тестування обробки помилок

Помилки — це як баги, тільки очікувані. Тому ми повинні переконатися, що наш додаток коректно обробляє ситуації, коли, наприклад, користувач запитує неіснуючий ресурс.

Приклад тесту для отримання неіснуючого користувача


def test_get_nonexistent_user():
    user_id = 999  # Якщо такого користувача немає
    response = client.get(f"/users/{user_id}")
    assert response.status_code == 404
    assert response.json() == {"detail": "Користувача не знайдено"}

Використання фікстур

Щоб уникнути дублювання коду (наприклад, створення користувачів у кожному тесті), ми можемо використовувати фікстури Pytest.

Фікстура для підготовки даних


import pytest

@pytest.fixture
def new_user():
    return {"email": "fixtureuser@example.com", "name": "Fixture User", "age": 30}

Використання фікстури в тестах


def test_create_user_with_fixture(new_user):
    token = get_test_token(user_id=1)
    headers = {"Authorization": f"Bearer {token}"}
    response = client.post("/users/", json=new_user, headers=headers)
    assert response.status_code == 201
    assert response.json()["email"] == new_user["email"]

Перевірка покриття коду

Після написання всіх тестів ми повинні переконатися, що покрили більшу частину нашого додатка. Для цього ми будемо використовувати плагін pytest-cov.

Встановлення pytest-cov:

pip install pytest-cov

Запуск тестів з покриттям:

pytest --cov=app

Результат виглядатиме приблизно так:

----------- coverage: platform linux, python 3.x -----------
Name                              Stmts   Miss  Cover
-----------------------------------------------------
app/main.py                          18      0   100%
app/models.py                        15      2    87%
app/schemas.py                       21      1    95%
app/routers/users.py                 42      3    93%
-----------------------------------------------------
TOTAL                                96      6    94%

Організація структури тестів

Якщо ваші тести розростуться, можливо, ви захочете організувати їх за модулями або функціональністю. Наприклад:

tests/
├── test_users.py
├── test_auth.py
├── test_errors.py

Підсумковий приклад повного набору тестів

Ось прикладні тести, які можна включити в ваш проєкт:

  1. Тести для всіх CRUD-операцій (GET, POST, PUT, DELETE);
  2. Перевірка захисних механік (валідація токенів, доступ до захищених ресурсів);
  3. Обробка помилок (404, некоректні дані);
  4. Тестування з використанням фікстур;
  5. Переконатися в високому рівні покриття коду.

З таким підходом ви будете спати спокійно і знати, що ваше API готове до будь-яких випробувань.

3
Опитування
Тестування аутентифікації через JWT, рівень 5, лекція 9
Недоступний
Тестування аутентифікації через JWT
Тестування аутентифікації через JWT
Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ