# Стратегия тестирования API --- ## 9 обязательных сценариев для каждого endpoint ### 1. Missing field → 422 ```python async def test_create_missing_field(async_client): response = await async_client.post("/api/v1/ideas", json={}) assert response.status_code == 422 ``` ### 2. Wrong type → 422 ```python async def test_create_wrong_type(async_client): response = await async_client.post("/api/v1/ideas", json={ "title": 123, # Должна быть строка "content": "test", }) assert response.status_code == 422 ``` ### 3. Expired/invalid token → 401 ```python async def test_unauthorized(async_client): response = await async_client.get("/api/v1/ideas", headers={ "Authorization": "Bearer invalid_token" }) assert response.status_code == 401 ``` ### 4. Wrong permissions → 403 ```python async def test_forbidden(async_client, user_token): response = await async_client.get( "/api/v1/admin/users", headers={"Authorization": f"Bearer {user_token}"}, ) assert response.status_code == 403 ``` ### 5. Not found → 404 ```python async def test_not_found(async_client, user_token): response = await async_client.get( "/api/v1/ideas/nonexistent", headers={"Authorization": f"Bearer {user_token}"}, ) assert response.status_code == 404 ``` ### 6. Conflict → 409 ```python async def test_duplicate_email(async_client): # Создать первого пользователя await async_client.post("/api/v1/auth/register", json={...}) # Попробовать создать с тем же email response = await async_client.post("/api/v1/auth/register", json={...}) assert response.status_code == 409 ``` ### 7. Success → 200/201 ```python async def test_create_success(async_client, user_token): response = await async_client.post( "/api/v1/ideas", json={"title": "Test", "content": "Content"}, headers={"Authorization": f"Bearer {user_token}"}, ) assert response.status_code == 201 data = response.json() assert data["title"] == "Test" ``` ### 8. Rate limit → 429 (если реализован) ```python async def test_rate_limit(async_client, user_token): for _ in range(100): await async_client.get("/api/v1/ideas", headers={...}) response = await async_client.get("/api/v1/ideas", headers={...}) assert response.status_code == 429 ``` ### 9. Idempotency → тот же результат при повторе ```python async def test_idempotent_delete(async_client, user_token, idea_id): response1 = await async_client.delete(f"/api/v1/ideas/{idea_id}", headers={...}) response2 = await async_client.delete(f"/api/v1/ideas/{idea_id}", headers={...}) assert response1.status_code == 204 assert response2.status_code == 404 # Уже удалено ``` --- ## Структура тестов ``` tests/ ├── conftest.py # Глобальные фикстуры ├── unit/ # изолированные тесты ├── integration/ │ ├── conftest.py # Фикстуры для API тестов │ ├── test_auth.py # 9 сценариев для auth │ ├── test_ideas.py # 9 сценариев для ideas │ └── test_admin.py # 9 сценариев для admin └── smoke/ └── test_health.py # smoke-тесты ``` --- ## [ASK] - Все ли 9 сценариев нужны для каждого endpoint? (рекомендация: да, но можно начать с успех + not found + unauthorized) - Нужны ли тесты на idempotency? (да, для DELETE и PATCH) - Как часто прогонять? (при каждом PR — обязательно, при каждом push — желательно)