16. REST API. Часть I. Пишем автотесты с Requests - qa-guru/knowledge-base GitHub Wiki
-
API (Application Programming Interface)
- Протоколы взаимодействия API
- Какое место в архитектуре занимает API
- Для чего нужны тесты на REST API
- Методы HTTP запроса
- Из чего состоит запрос к API
- Из чего состоит ответ от API
- Коды ответа HTTP
- Работа в Postman
- Работа с библиотекой Requests
- Валидация ответа от сервера(схем ответа)
- Verify параметр в запросе
- Параметры запроса
- Структура проекта с тестами
API — это интерфейс, который позволяет программам взаимодействовать друг с другом. API определяет набор правил и механизмов, с помощью которых одна программа может взаимодействовать с другой программой. API позволяет программам обмениваться данными и функциями между собой.
RESTful API/REST API (Representational State Transfer Protocol) — это архитектурный стиль взаимодействия компонентов распределённого приложения в сети. REST представляет собой согласованный набор ограничений(рекомендаций).
GraphQL — это язык запросов к API и среда выполнения запросов с открытым исходным кодом, созданные Facebook в 2012 году. GraphQL позволяет клиентам запрашивать только те данные, которые им нужны, и ничего больше.
SOAP (Simple Object Access Protocol) — это протокол обмена структурированными сообщениями в распределённой вычислительной среде. SOAP использует XML для обмена сообщениями между компонентами программного обеспечения.
JSON-RPC и XML-RPC (Remote Procedure Call) — это протокол удалённого вызова процедур, который позволяет вызывать функции на удалённом сервере. JSON-RPC и XML-RPC используют JSON и XML для передачи данных.
gRPC(gRPC Remote Procedure Calls) — это высокопроизводительный фреймворк для RPC, разработанный в Google. gRPC использует протокол HTTP/2 для передачи данных и Protocol Buffers для сериализации данных(преобразования данных в бинарный формат).
API буквально связывают клиентскую и серверную часть веб-приложения и помогают быстрее и эффективнее обращаться к серверу. Все пользовательские запросы выполняются через API. Каждый клик на сайте, каждая заполненная форма отправляет запрос к серверу через API, возвращает запрошенные данные и код ответа.
С помощью REST API кодовая база тестов получается более стабильной и помогает выполнять их быстрее. Также во время выполнения тестов на REST API машине не приходится каждый раз открывать окно браузера, что положительно сказывается на производительности.
К примеру, тест странице авторизации может быть основан на использовании UI приложения. В таком случае для каждого шага теста необходимо будет использовать элементы веб-страницы и вводить данные пользователя. Также во время выполнения теста системе надо будет открыть браузер для запуска тестов. С помощью тестов на REST API нет необходимости в использовании элементов страницы и для запуска можно обойтись без браузера.
Основные методы HTTP запроса (более подробно можно ознакомиться в документации на русском языке):
-
GET
— запрашивает ресурс (может только извлекать данные); -
HEAD
— запрашивает ресурс без тела ответа; -
POST
— отправляет сущности ресурсу; -
PUT
— заменяет сущности ресурса данными запроса; -
DELETE
— удаляет ресурс; -
CONNECT
— устанавливает соединение к серверу; -
OPTIONS
— описывает параметры соединения с сервером; -
TRACE
— вызывает возвращаемое тестовое сообщения с сервера; -
PATCH
— частично изменяет ресурс.
Идемпотентные методы — это методы, которые можно вызывать несколько раз подряд, не изменяя состояние сервера.
К идемпотентным методам относятся GET
, PUT
, DELETE
, HEAD
, OPTIONS
, TRACE
.
- Из метода HTTP запроса(GET, POST, PUT, DELETE и т.д.);
- Из URL-адреса, по которому отправляется запрос(URL);
- Эндпоинта(Endpoint) — это конечная точка веб-сервиса, к которой обращается клиент;
- Параметров запроса(Params)- то что указываются после знака вопроса в URL;
- Заголовков запроса(Headers);
- Тела запроса.
- Куки(Cookies).
- Из кода ответа HTTP;
- Из заголовков ответа;
- Из тела ответа(может быть пустым или в формате JSON, XML, HTML и т.д.).
- Из куков(Cookies).
Коды ответа помогают определить успешность совершённого запроса. Коды ответа делятся на пять групп:
- Информационные — 100-199;
- Успешные — 200-299;
- Перенаправления — 300-399;
- Клиентская ошибка — 400-499;
- Серверная ошибка — 500-599.
Наиболее популярные коды ответов:
-
200
—OK
запросы успешно выполнен; -
201
—Created
запрос успешно выполнен и создан новый ресурс; -
202
—Accepted
запрос принят, но еще не обработан; -
400
—Bad Request
сервер не может обработать запрос из-за неверного синтаксиса; -
401
—Unauthorized
необходима аутентификация(авторизация) пользователя; -
403
—Forbidden
сервер понял запрос, но отказывается его выполнять(уровень прав клиента не позволяет получить ему содержимое ответа); -
404
—Not Found
сервер не может найти запрашиваемый ресурс; -
418
—I'm a teapot
сервер отказывается выполнять кофейные запросы; -
500
—Internal Server Error
общая ошибка сервера(внутренняя ошибка сервера, сервер не знает как обработать запрос); -
502
—Bad Gateway
сервер, действуя в качестве шлюза или прокси-сервера, получил недопустимый ответ от вышестоящего сервера; -
503
—Service Unavailable
сервер временно не может обрабатывать запросы(сервер не готов принять запрос, сервер выключен или перегружен.)
Все коды ответов HTTP можно изучить в официальной русскоязычной документации.
Postman — это инструмент для тестирования API, который позволяет отправлять запросы к API, а также тестировать их. Postman позволяет отправлять запросы различных типов(GET, POST, PUT, DELETE и т.д.), а также просматривать ответы от сервера.
Запрос в Postman можно скопировать вручную из панели разработчика браузера, а также можно скопировать одним нажатием кнопки.
Для копирования запроса необходимо нажать правой кнопкой мыши на запросе и выбрать пункт Copy as cURL(cmd)
или Copy as cURL(bash)
и вставить в Postman в строку запроса(URL).
Запрос в Postman состоит из:
- Метода HTTP запроса(GET, POST, PUT, DELETE и т.д.);
- URL-адреса, по которому отправляется запрос(URL);
- Эндпоинта(Endpoint) — это конечная точка веб-сервиса, к которой обращается клиент;
- Параметров запроса(Params)- то что указываются после знака вопроса в URL;
- Отображения параметров запроса в виде таблицы;
- Заголовков запроса(Headers);
- Ответа от сервера(Response).
- Тела запроса(Body).
Скопировать запрос с Postman можно в виде кода на различных языках программирования. Для этого необходимо нажать кнопку Code
и выбрать язык программирования.
Requests — это библиотека для отправки HTTP запросов в Python. Библиотека Requests позволяет отправлять запросы различных типов(GET, POST, PUT, DELETE и т.д.), а также просматривать ответы от сервера.
Для установки библиотеки Requests необходимо выполнить команду:
pip install requests
Пример запроса
import requests
url = 'https://reqres.in/api/users'
payload = {
"name": "morpheus",
"job": "leader"
}
response = requests.post(url, data=payload)
print(response.json())
Код выше можно переписать немного по-другому, вынести URL в переменную, а эндпоинт в отдельную переменную.
import requests
url = 'https://reqres.in'
endpoint = '/api/users'
payload = {
"name": "morpheus",
"job": "leader"
}
def test_create_user():
response = requests.post(url + endpoint, data=payload)
assert response.status_code == 201
assert response.json()['name'] == 'morpheus' # Проверка имени
assert response.json()['job'] == 'leader' # Проверка должности
Если в запросе необходимо передать заголовки, то это можно сделать следующим образом:
import requests
url = 'https://reqres.in'
endpoint = '/api/users'
name = 'morpheus'
job = 'leader'
payload = {
"name": name,
"job": job
}
headers = {
'Content-Type': 'application/json'
}
def test_create_user():
response = requests.post(url + endpoint, json=payload, headers=headers)
assert response.status_code == 201
assert response.json()['name'] == name # Проверка имени
assert response.json()['job'] == job # Проверка должности
Если в запросе необходимо передать авторизацию, то это можно сделать следующим образом:
import requests
url = 'https://reqres.in'
endpoint = '/api/users'
headers = {
'Content-Type': 'application/json'
'Authorization': 'Bearer token'
}
def test_create_user():
response = requests.get(url + endpoint, headers=headers)
assert response.status_code == 200
Для валидации ответа от сервера можно использовать библиотеку jsonschema
. Для установки библиотеки jsonschema
необходимо выполнить команду:
pip install jsonschema
Для генерации схем ответа можно использовать онлайн-сервисы, например jsonschema.net или liquid-technologies.com.
Пример схемы ответа:
Нажать, чтобы раскрыть
# post_users.json
{
"$schema": "http://json-schema.org/draft-04/schema#", # данная строчка сгенерирована автоматически и ее можно удалять
"type": "object",
"properties": {
"name": {
"type": "string"
},
"job": {
"type": "string"
},
"id": {
"type": "string"
},
"createdAt": {
"type": "string"
}
},
"required": [
"name",
"job",
"id",
"createdAt"
]
}
В схеме выше указаны типы данных, которые должны быть в ответе от сервера. Также указаны обязательные поля. При валидации ответа от сервера, если какого-то поля не будет в ответе, или он будет другого типа, то тест упадет.
import requests
from jsonschema import validate
url = 'https://reqres.in'
endpoint = '/api/users'
payload = {
"name": "morpheus",
"job": "leader"
}
def test_create_user():
response = requests.post(url + endpoint, data=payload)
assert response.status_code == 201
# Валидация ответа от сервера
with open('post_users.json') as file:
schema = json.load(file)
validate(instance=response.json(), schema=schema) # Валидация ответа от сервера. Также можно записать так validate(response.json(), schema)
Также схемы можно группировать в одном файле, например schemas.py
:
Нажать, чтобы раскрыть
# schemas.py
post_users = {
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"name": {
"type": "string"
},
"job": {
"type": "string"
},
"id": {
"type": "string"
},
"createdAt": {
"type": "string"
}
},
"required": [
"name",
"job",
"id",
"createdAt"
]
}
single_user = {
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"data": {
"type": "object",
"properties": {
"id": {
"type": "integer"
},
"email": {
"type": "string"
},
"first_name": {
"type": "string"
},
"last_name": {
"type": "string"
},
"avatar": {
"type": "string"
}
},
"required": [
"id",
"email",
"first_name",
"last_name",
"avatar"
]
},
"support": {
"type": "object",
"properties": {
"url": {
"type": "string"
},
"text": {
"type": "string"
}
},
"required": [
"url",
"text"
]
}
},
"required": [
"data",
"support"
]
}
Если схемы сгруппированные в одном файле(schemas.py), то можно использовать следующий код:
import requests
from jsonschema import validate
from schemas import post_users
url = 'https://reqres.in'
endpoint = '/api/users'
payload = {
"name": "morpheus",
"job": "leader"
}
def test_create_user():
response = requests.post(url + endpoint, data=payload)
assert response.status_code == 201
body = response.json()
# Валидация ответа от сервера
validate(body , post_users)
Если нужно жёстко валидировать ответ от сервера, то можно указать в схеме "additionalProperties": False
.
Если указано "additionalProperties": False
, то в ответе от сервера не должно быть дополнительных полей, которые не указаны в схеме. Иначе тест упадет.
Если указано "additionalProperties": True
, то в ответе от сервера могут быть дополнительные поля, которые не указаны в схеме.
Пример схемы с "additionalProperties": False
и если в ответе от сервера будет дополнительное поле
Параметр verify
в запросе позволяет проверить SSL-сертификат. По умолчанию параметр verify
равен True
. Если установить параметр verify
в False
, то запрос будет выполнен без проверки SSL-сертификата(к примеру при тестировании локального сервера).
Пример запроса с параметром verify
:
import requests
url = 'https://reqres.in'
endpoint = '/api/users'
payload = {
"name": "morpheus",
"job": "leader"
}
def test_create_user():
response = requests.post(url + endpoint, data=payload, verify=False)
assert response.status_code == 201
Разница между параметрами запроса data
и json
:
-
data
— отправляет данные в виде строки; -
json
— отправляет данные в виде JSON.
Пример запроса с параметром json
:
import requests
url = 'https://reqres.in'
endpoint = '/api/users'
payload = {
"name": "morpheus",
"job": "leader"
}
def test_create_user():
response = requests.post(url + endpoint, json=payload)
assert response.status_code == 201
При отправке запроса с параметром json
, заголовок Content-Type
автоматически устанавливается в application/json
.
При отправке запроса с параметром data
, заголовок Content-Type
устанавливается в application/x-www-form-urlencoded
.
Проекты с тестами обычно придерживаются следующей структуры:
project
├── schemas
| ├── post_users.json
| └── ...
или
├── schemas.py
|
└── tests
| └── api
| ├── test_create_user.py
| ├── ...
| └── conftest.py
|
└── requirements.txt