Initial commit: VoIdeaAI - voice-first AI idea assistant
This commit is contained in:
@@ -0,0 +1,117 @@
|
||||
# Стратегия тестирования 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 — желательно)
|
||||
Reference in New Issue
Block a user