Files
voidea/template/docs/api-testing-strategy.md

118 lines
3.9 KiB
Markdown

# Стратегия тестирования 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 — желательно)