Files

3.7 KiB

Стандарты тестирования

Философия

Код без тестов — это не код, а предложение. Если функцию нельзя проверить — она либо не нужна, либо её нужно переписать.


Пирамида тестов

        /\          E2E (10%): сквозные сценарии
       /  \
      /    \
     /──────\     Integration (20%): API, БД, внешние сервисы
    /        \
   /──────────\  Unit (70%): изолированные модули
  /            \

Типы тестов

Unit-тесты (tests/unit/)

  • Тестируют один класс/функцию в изоляции
  • Внешние зависимости мокаются
  • Быстрые (миллисекунды)
  • Пример: тест сервиса с mocked репозиторием
async def test_idea_service_create():
    service = IdeaService(mock_db)
    idea = await service.create(user_id="1", title="Test", content="Content")
    assert idea.title == "Test"
    assert idea.status == "draft"

Integration-тесты (tests/integration/)

  • Тестируют взаимодействие компонентов
  • Используют реальную БД (SQLite в памяти)
  • Проверяют API endpoints, БД запросы
  • Пример: тест регистрации пользователя
async def test_register_user(async_client):
    response = await async_client.post("/api/v1/auth/register", json={
        "username": "test",
        "email": "test@test.com",
        "password": "secret123",
    })
    assert response.status_code == 201
    data = response.json()
    assert "access_token" in data

Smoke-тесты (tests/smoke/)

  • Минимум 1 тест на каждый endpoint
  • Проверяют что endpoint отвечает и возвращает корректный статус
  • Быстрая проверка здоровья системы
async def test_health_endpoint(async_client):
    response = await async_client.get("/health")
    assert response.status_code == 200
    assert response.json()["status"] == "healthy"

Покрытие

  • Общее покрытие: > 80%
  • Критический код (auth, security, payments): 100%
  • Новый код: без тестов не принимается в PR

Что тестировать

Обязательно (9 сценариев для каждого endpoint)

  1. Missing field → 422
  2. Wrong type → 422
  3. Expired/invalid token → 401
  4. Wrong permissions → 403
  5. Not found → 404
  6. Conflict → 409
  7. Success → 200/201
  8. Rate limit → 429 (если реализован)
  9. Idempotency → тот же результат при повторе

Для каждого сервиса

  • Успешное выполнение
  • Ошибка валидации
  • Ошибка БД
  • Граничные случаи (пустой список, null, максимальная длина)

Конфигурация pytest

# pyproject.toml или pytest.ini
[tool.pytest.ini_options]
asyncio_mode = "auto"
testpaths = ["tests"]
python_files = ["test_*.py"]

[ASK] Вопросы по тестированию

  • Нужен ли coverage порог в CI? (рекомендуется 80%)
  • Использовать ли vcrpy для записи ответов внешних API? (да, для AI провайдеров)
  • Нужны ли performance-тесты? (да, для критических endpoint'ов)