✅ Решения заданий
⚡ Ключевые паттерны решений
- Фильтрация активных:
[c for c in resp.json() if c["is_active"]] - Негативный тест:
assert resp.status_code == 422при пустомjson={} - Рост списка: GET → len → POST → GET → assert new == old + 1
- reqres.in:
user = data["data"]→ assert поля
Решение 1: Список активных компаний
# test_companies.py
import requests
def test_get_active_companies():
url = "http://5.101.50.27:8000/company/list"
# 1. Отправляем GET-запрос
response = requests.get(url)
# 2. Проверяем успешный статус
assert response.status_code == 200, f"Ошибка: статус {response.status_code}"
# 3. Разбираем JSON-ответ
companies = response.json()
# 4. Фильтруем только активные компании
active_companies = [company for company in companies if company["is_active"]]
# 5. Проверяем количество активных компаний
assert len(active_companies) >= 3, \
f"Ожидалось >=3 активных компаний, но найдено {len(active_companies)}"
print(f"Тест пройден! Найдено {len(active_companies)} активных компаний.")
Объяснение
response.json()— разбирает JSON-массив в Python list- List comprehension
[c for c in companies if c["is_active"]]— фильтрует только активные len(active_companies) >= 3— гибкое условие (не хардкодим точное число)
Решение 2: Негативный тест — пустое тело
# test_companies.py
import requests
BASE_URL = "http://5.101.50.27:8000"
def test_create_company_empty_body():
"""Отправка пустого JSON должна вернуть 422"""
resp = requests.post(BASE_URL + "/company/create", json={})
response = resp.json()
assert resp.status_code == 422, \
f"Ожидался 422, получен {resp.status_code}"
assert response["detail"][0]["msg"] == "Field required"
Объяснение
- Сервер требует поле
name— без него возвращает 422 Unprocessable Entity - Структура ошибки Pydantic:
detail[0]["msg"]содержит текст "Field required" - Негативные тесты важны: они проверяют, что API корректно отклоняет некорректные запросы
Решение 3: Рост списка компаний
# test_companies.py
import requests
BASE_URL = "http://5.101.50.27:8000"
def test_create_company_increases_count():
"""Тест: создание компании увеличивает список на 1"""
# 1. Получаем текущий список компаний
resp = requests.get(BASE_URL + "/company/list")
assert resp.status_code == 200, f"Ошибка: {resp.status_code}"
companies_before = resp.json()
initial_count = len(companies_before)
# 2. Создаём новую компанию
new_company = {
"name": "Test Company",
"description": "Automated test creation"
}
resp_create = requests.post(BASE_URL + "/company/create", json=new_company)
assert resp_create.status_code == 201, f"Ошибка создания: {resp_create.status_code}"
# 3. Повторно получаем список компаний
resp_after = requests.get(BASE_URL + "/company/list")
assert resp_after.status_code == 200, f"Ошибка: {resp_after.status_code}"
companies_after = resp_after.json()
final_count = len(companies_after)
# 4. Проверяем: стало на 1 больше
assert final_count == initial_count + 1, \
f"Ожидалось {initial_count + 1} компаний, найдено {final_count}"
print(f"Тест пройден: до {initial_count}, после {final_count}")
Объяснение
- Не хардкодим ID компании — создаём новую и сразу проверяем изменение списка
- Три запроса: GET → POST (create) → GET — стандартный паттерн для тестов мутаций
assert final_count == initial_count + 1— точная проверка на +1, не просто "> 0"
Решение 4: GET к reqres.in
⚠️ С 2024 года reqres.in требует бесплатный ключ
x-api-key: reqres-free-v1 — без него ответ 401. Передаём заголовок HEADERS в каждый запрос.
# test_reqres.py
import requests
import pytest
BASE_URL = "https://reqres.in/api/users"
HEADERS = {"x-api-key": "reqres-free-v1"} # бесплатный ключ reqres.in (с 2024)
@pytest.mark.parametrize("user_id, expected_first_name, expected_last_name, expected_email", [
(2, "Janet", "Weaver", "janet.weaver@reqres.in"),
])
def test_get_existing_user(user_id, expected_first_name, expected_last_name, expected_email):
"""Тест: получение существующего пользователя"""
response = requests.get(f"{BASE_URL}/{user_id}", headers=HEADERS)
# Проверяем статус
assert response.status_code == 200, f"Ожидался статус 200, получен {response.status_code}"
data = response.json()
# Проверяем структуру ответа
assert "data" in data, "Ответ API не содержит ключ 'data'"
user = data["data"]
# Проверяем данные пользователя
assert user["id"] == user_id
assert user["first_name"] == expected_first_name, \
f"Ожидалось '{expected_first_name}', получено '{user['first_name']}'"
assert user["last_name"] == expected_last_name
assert user["email"] == expected_email
def test_get_non_existing_user():
"""Тест: несуществующий пользователь → 404"""
user_id = 23
response = requests.get(f"{BASE_URL}/{user_id}", headers=HEADERS)
assert response.status_code == 404, f"Ожидался статус 404, получен {response.status_code}"
assert response.text == "{}", f"Ожидался пустой JSON, получен {response.text}"
Объяснение
@pytest.mark.parametrize— позволяет легко добавлять тест-кейсы без дублирования кодаdata["data"]— ответ reqres.in вложен в ключ "data", нужно «пробурить» структуру- Тест на несуществующего пользователя — проверяем 404 и пустое тело
{}