📖 Теория: Summary session 7 — Requests
⚡ Requests за 2 минуты
requests — библиотека для HTTP-запросов. resp = requests.get(url) → resp.status_code, resp.json().
requests.get(url)/requests.post(url, json=data)/requests.patch()/requests.delete()resp.status_code— 200 OK, 201 Created, 404 Not Found, 500 Server Errorresp.json()— dict или list;resp.text— строка;resp.headers— словарь заголовков- В тесте:
assert resp.status_code == 200+assert resp.json()["field"] == value
Клиент-серверная архитектура
Из лекции: клиент — устройство или программа, которая отправляет запросы (браузер, мобильное приложение, Python-скрипт). Сервер — принимает запросы, обрабатывает и возвращает ответы. Клиентов может быть много, сервер — один.
| Протокол | Расшифровка | Особенность |
|---|---|---|
| HTTP | HyperText Transfer Protocol | Данные передаются открыто |
| HTTPS | HTTP Secure | Данные зашифрованы (TLS); обязателен для паролей, платёжных данных |
Состав HTTP-запроса
Из лекции: HTTP-запрос состоит из четырёх частей:
- URL — адрес ресурса:
http://5.101.50.27:8000/company/list - Метод — что делать с ресурсом (GET, POST, PATCH, DELETE…)
- Заголовки (Headers) — дополнительные параметры:
Content-Type,Authorization,Accept - Тело (Body) — данные, которые передаются серверу (JSON, форма); у GET-запросов обычно пустое
HTTP-методы (из лекции)
| Метод | Описание | Пример |
|---|---|---|
| GET | Получение данных (без изменений) | Список компаний, профиль пользователя |
| POST | Создание нового ресурса | Создать компанию, авторизоваться |
| PUT | Полное обновление ресурса | Заменить все поля пользователя |
| PATCH | Частичное обновление | Изменить только имя или статус |
| DELETE | Удаление ресурса | Удалить компанию по ID |
Состав HTTP-ответа
- Статус-код — трёхзначное число: 200 OK, 201 Created, 404 Not Found, 500 Internal Server Error
- Заголовки —
Content-Type: application/jsonи другие - Тело (Body) — данные от сервера (JSON, HTML); может отсутствовать
| Категория | Описание | Примеры |
|---|---|---|
| 1xx | Информационные | 100, 101 |
| 2xx | Успешные запросы | 200 OK, 201 Created |
| 3xx | Перенаправления | 301 Moved Permanently, 304 Not Modified |
| 4xx | Ошибки клиента | 400 Bad Request, 404 Not Found |
| 5xx | Ошибки сервера | 500 Internal Server Error, 503 Unavailable |
Библиотека requests: установка и основы
Из лекции: requests — популярная Python-библиотека для отправки HTTP-запросов. Упрощает работу с API.
# Установка (PowerShell/терминал)
pip install requests
# Проверка установки
pip show requests
# Установка конкретной версии
pip install requests==2.31.0
# Обновление до последней версии
pip install --upgrade requests
Базовые методы
# test_api.py
import requests
BASE_URL = "http://5.101.50.27:8000"
# GET — получение данных
resp = requests.get(BASE_URL + "/company/list")
# POST — создание / авторизация (данные передаём как json=)
resp = requests.post(BASE_URL + "/auth/login", json={"username": "harrypotter", "password": "expelliarmus"})
# PATCH — частичное обновление (с токеном в query-параметре)
resp = requests.patch(BASE_URL + f"/company/update/{company_id}?client_token={token}", json={"name": "New Name"})
# DELETE — удаление
resp = requests.delete(BASE_URL + f"/company/{company_id}?client_token={token}")
Объект Response
Из лекции: каждый метод requests возвращает объект Response с атрибутами:
| Атрибут / Метод | Что возвращает | Когда использовать |
|---|---|---|
resp.status_code | int: 200, 201, 404… | Всегда проверяем первым |
resp.json() | dict или list (Python-объект) | Когда сервер отвечает JSON |
resp.text | str — тело ответа как строка | Отладка, не-JSON ответы |
resp.headers | dict заголовков ответа | Проверить Content-Type и другие |
resp.url | str — финальный URL | Отладка редиректов |
resp.text всегда возвращает строку — даже если содержимое JSON. Обращаться к полям через data["key"] нельзя. resp.json() автоматически парсит JSON в dict/list — с ним работаешь как со словарём.
Работа с JSON в Python
Из лекции: JSON и Python очень похожи, но есть отличия:
| JSON | Python |
|---|---|
true / false | True / False |
null | None |
Строки только в двойных кавычках "key" | Строки в одинарных или двойных |
# test_json.py
import json
company_json = """
{
"id": 111,
"isActive": true,
"name": "QA Studio"
}
"""
def test_parse_json():
company = json.loads(company_json) # строка JSON -> dict Python
assert company["id"] == 111
assert company["isActive"] is True # JSON true -> Python True
- Одинарные кавычки
'key'вместо двойных"key"— вызываютjson.JSONDecodeError - Отсутствие запятой между элементами
- Лишняя запятая перед
}или] - Использование
True/Noneвместоtrue/nullпри ручном написании JSON
XClients API: практика из лекции
Из лекции: XClients — сервис записи на приём к специалистам. Базовый URL: http://5.101.50.27:8000. Модули: auth, company, employee, superuser.
Сценарий из лекции (шаги по порядку)
- GET
/company/list— получить список компаний - POST
/auth/login— авторизоваться, получитьuser_token - POST
/company/create— создать компанию - GET
/company/list— убедиться, что компания появилась - DELETE
/company/{id}?client_token=...— удалить компанию - GET
/company/list— убедиться, что компания исчезла
# test_x_clients.py
import requests
BASE_URL = "http://5.101.50.27:8000"
def test_simple_req():
resp = requests.get(BASE_URL + "/company/list")
assert resp.status_code == 200
assert resp.headers["Content-Type"] == "application/json"
response_body = resp.json()
first_company = response_body[0]
assert first_company["name"] == "QA Студия 'ТестировщикЪ'"
Класс CompanyApi
Из лекции: выносим логику запросов в отдельный класс — тесты становятся чище, API-вызовы переиспользуются, при изменении сервера правим только класс.
# company_api.py
import requests
class CompanyApi:
"""Класс для взаимодействия с API компаний."""
def __init__(self, url):
self.url = url
def get_company_list(self):
resp = requests.get(self.url + "/company/list")
assert resp.status_code == 200, f"Ожидался 200, получен {resp.status_code}"
return resp.json()
def get_token(self, user, password):
creds = {"username": user, "password": password}
resp = requests.post(self.url + "/auth/login", json=creds)
assert resp.status_code == 200, f"Ожидался 200, получен {resp.status_code}"
return resp.json()["user_token"]
def create_company(self, name, description=""):
company = {"name": name, "description": description}
resp = requests.post(self.url + "/company/create", json=company)
assert resp.status_code == 201, f"Ожидался 201, получен {resp.status_code}"
return resp.json()
def get_company(self, company_id):
resp = requests.get(self.url + f"/company/{company_id}")
assert resp.status_code == 200, f"Ожидался 200, получен {resp.status_code}"
return resp.json()
def edit_company(self, company_id, new_name, new_descr):
token = self.get_token("harrypotter", "expelliarmus")
url = f"{self.url}/company/update/{company_id}?client_token={token}"
resp = requests.patch(url, json={"name": new_name, "description": new_descr})
assert resp.status_code == 200, f"Ожидался 200, получен {resp.status_code}"
return resp.json()
def delete_company(self, company_id):
token = self.get_token("harrypotter", "expelliarmus")
url = f"{self.url}/company/{company_id}?client_token={token}"
resp = requests.delete(url)
assert resp.status_code == 200, f"Ожидался 200, получен {resp.status_code}"
return resp.json()
Тест с использованием CompanyApi
# test_x_clients.py
from company_api import CompanyApi
BASE_URL = "http://5.101.50.27:8000"
def test_create_company_increases_count():
"""Тест: создание компании увеличивает список на 1."""
api = CompanyApi(BASE_URL)
companies_before = api.get_company_list()
initial_count = len(companies_before)
api.create_company(name="Test Company", description="Automated test")
companies_after = api.get_company_list()
assert len(companies_after) == initial_count + 1
- Нет дублирования
requests.get()/requests.post()в каждом тесте - Проверки статус-кодов — внутри класса, тесты чище
- Если API изменится — правим только
CompanyApi, тесты не трогаем - Легко переиспользовать в разных тестах
Итог: блок API-тестирования — начало (уроки 13–14)
| Урок | Тема | Ключевые концепции |
|---|---|---|
| 13 | Введение в Requests | HTTP, requests, Response, json(), CompanyApi |
| 14 | Summary 7 (этот урок) | Повторение: requests, JSON, CompanyApi, EmployeeApi (ДЗ) |
| 15 | Автоматизация API-тестов | pytest-фикстуры, параметризация, схемы ответов |
| 16 | Summary 8 | Итоговое повторение курса |