HTTP запросы

Описание запросов

При помощи механизма HTTP-запросов можно напрямую обращаться к веб-серверу минуя взаимодействия с браузером. Этот механизм в первую очередь предназначен для дополнения браузерного тестирования, а не для создания самостоятельных api-тестов.

Использовать HTTP-запросы можно в любом тесте в не зависимости от браузера. Но если не нужно выполнить только HTTP-запросы, то можно обойтись без запуска обычного браузера (например chrome или firefox) что значительно уменьшит время выполнения тестов. Для этого достаточно указать в качестве используемого браузера встроенный браузер http. Этот браузер умеет выполнять только запросы, по этому если в тесте будут ещё и обычные команды, то они будут пропущены (т.е. завершатся со статусом SKIPPED).

Механизм HTTP-запросов автоматически синхронизирует cookie текущего браузера с cookie запроса. Т.е. при отправки запроса используются cookie установленные для текущей браузерной сессии, а после завершении запроса они автоматически обновляются. Если нужно установить собственные cookie в запросе, то можно использовать команды для работы с cookies.

МЕТОД[ endpoint {, endpoint }, [ params ]]( инструкции запроса, [ ,content_type ] [ ,redirects ] [ ,timeout ] )[( { подстановка, } { параметр=значение } )]

Для описания запроса служат следующие команды: GET, POST, PUT, DELETE, PATCH, HEAD или OPTIONS они определяют используемый метод запроса. После указания метода нужно в квадратных скобках передают адрес запроса. Обычно адресом запроса является URL конкретного метода веб-api, но вместо неё можно передать список URL-строк. Такой список может быть возвращён кванторами ALL или ANY при выполнении браузерного тестирования. Запрос будет выполнен последовательно для каждого переданного URL.

Инструкции запроса служат для указания данных передаваемых в запросе и валидации его результата. Они будут выполнены для каждого запроса (т.е. для каждого URL указанного в endpoint). Порядок следования инструкций не важен.

Аргументы:

  • endpoint - Адрес запроса.
  • params - Словарь с url-параметрами запроса По умолчанию - {}
  • content_type - Тип контента запроса (в настоящий момент поддерживается только JSON) По умолчанию - JSON
  • redirects - Следовать перенаправлениями в запросе По умолчанию - False
  • timeout - Максимальное время выполнения запроса. По умолчанию - CONFIG.HTTP_TIMEOUT

Пример:

TEST["Проверка доступности ссылок для скачивание файлов"](
    URL("http://the-internet.herokuapp.com/download")
    
    , "Проверяем доступность всех URL файлов"
    , HEAD[ALL(".example > a", "attr::href")](
        ASSERT(STATUS == 200)
        , timeout=25
    )
    
    , test_id="download"
    , tags = "files,download"
)

Объекты запроса

Описания запросов являются самостоятельными объектами, они не обязательно должны быть определены внутри теста. За счёт этого один и тоже описание запроса может быть использовано в разных тестах и даже может быть помещено в пространства имён.

Пример:

scope = SCOPE("api")
token = {"user_name": "Meta", "password": "Test"}

# создаём описание запроса и помещаем его в пространство имён api/make_token
scope.make_token = POST["/Account/get_token"](
    # валидация ответа сервера
    STATUS == STATUS.OK
    , CHECK_JSON_SHEMA("api/shema/token.json")
    # устанавливаем переменную token как тело запроса
    , PAYLOAD(token)
)

TEST["Проверяем получение токена авторизации"](
    "scope::api/make_token"  # Ссылка на пространство имён, можно заменить объектом NP("api", "make_token")
    
    , tags="api"
    , test_id="api_user"
)

Используя существующий объект запроса можно создать его копию с изменённым адресом запроса (endpoint) или его параметрами (params). Для этого нужно вызвать объект запроса передав ему одну или несколько строк для подстановки в строку адреса и/или словарь параметров запроса. Переданные при вызове строки будут подставлены в строку адреса заменив в них шаблон вида { n } где n - индекс строки для подстановки. Кроме того возможен вариант подстановки с применением оператора интерполяции строк.

Пример:

# объект запроса для удаления пользователя
del_user = DELETE["/Account/User/{ 0 }"](  # в место { 0 } будет подставлен id пользователя
    STATUS == STATUS.OK
)

...

# удаляем пользователя передав ему идентификатор и объекта запроса get_user
del_user(CONTENT(get_user)["user_id"])

Инструкции запроса

STATUS | STATUS(запрос [ , cached ])

Возвращает статус-код ответа сервера. Может быть использована вне описания запроса, в этом случае первым аргументом нужно передать объект запроса у которого нужно получить код-статуса.

Аргумент cached может принимать следующие значения: True, False и None. Данные в любом случае будут возвращены из кэша, но True означает что возвращаемый результат будет взят только из кэша. False - что будет выполнен запрос к серверу, а полученный результат будет закэширован. None - если значение заголовка Cache-Control будет равно no-cache, то кэш будет инвалидирован (т.е. поведение аналогично значению False) иначе нет.

Аргументы:

  • Запрос - Объект запроса для которого нужно вернуть код-статуса.
  • cached - Режим инвалидации кэша (описан выше).

Для удобства определения кода-статуса в пространства имён команды STATUS были добавлены идентификаторы со следующими кодами:

Код Идентификатор Код Идентификатор Код Идентификатор
100 CONTINUE 308 PERMANENT_REDIRECT 423 LOCKED
101 SWITCHING_PROTOCOLS 400 BAD_REQUEST 424 FAILED_DEPENDENCY
102 PROCESSING 401 UNAUTHORIZED 425 TOO_EARLY
103 EARLY_HINTS 402 PAYMENT_REQUIRED 426 UPGRADE_REQUIRED
200 OK 404 NOT_FOUND 428 PRECONDITION_REQUIRED
201 CREATED 405 METHOD_NOT_ALLOWED 429 TOO_MANY_REQUESTS
202 ACCEPTED 406 NOT_ACCEPTABLE 431 REQUEST_HEADER_FIELDS_TOO_LARGE
203 NON_AUTHORITATIVE_INFORMATION 407 PROXY_AUTHENTICATION_REQUIRED 451 UNAVAILABLE_FOR_LEGAL_REASONS
204 NO_CONTENT 408 REQUEST_TIMEOUT 500 INTERNAL_SERVER_ERROR
205 RESET_CONTENT 409 CONFLICT 501 NOT_IMPLEMENTED
206 PARTIAL_CONTENT 410 GONE 502 BAD_GATEWAY
207 MULTI_STATUS 411 LENGTH_REQUIRED 503 SERVICE_UNAVAILABLE
208 ALREADY_REPORTED 412 PRECONDITION_FAILED 504 GATEWAY_TIMEOUT
208 ALREADY_REPORTED 413 REQUEST_ENTITY_TOO_LARGE 505 HTTP_VERSION_NOT_SUPPORTED
300 MULTIPLE_CHOICES 414 REQUEST_URI_TOO_LONG 506 VARIANT_ALSO_NEGOTIATES
301 MOVED_PERMANENTLY 415 UNSUPPORTED_MEDIA_TYPE 507 INSUFFICIENT_STORAGE
302 FOUND 416 REQUESTED_RANGE_NOT_SATISFIABLE 508 LOOP_DETECTED
303 SEE_OTHER 417 EXPECTATION_FAILED 510 NOT_EXTENDED
304 NOT_MODIFIED 418 IM_A_TEAPOT 511 NETWORK_AUTHENTICATION_REQUIRED
305 USE_PROXY 421 MISDIRECTED_REQUEST
307 TEMPORARY_REDIRECT 422 UNPROCESSABLE_ENTITY

HEADERS | HEADERS(запрос, [ cached ])

Возвращает заголовки ответа сервера. Может быть использована вне описания запроса, в этом случае первым аргументом нужно передать объект запроса у которого нужно получить заголовки ответа.

Аргумент cached может принимать следующие значения: True, False и None. Данные в любом случае будут возвращены из кэша, но True означает что возвращаемый результат будет взят только из кэша. False - что будет выполнен запрос к серверу, а полученный результат будет закэширован. None - если значение заголовка Cache-Control будет равно no-cache, то кэш будет инвалидирован (т.е. поведение аналогично значению False) иначе нет.

Аргументы:

  • Запрос - Объект запроса для которого нужно вернуть заголовки ответа.
  • cached - Режим инвалидации кэша (описан выше).

Заголовки ответа представляют собой словарь доступ к значениям которого можно получить как через обращение к атрибуту объекта, так и через обращение к его ключу.

Пример:

TEST["Параметры GET запроса"](
    GET["https://postman-echo.com/get", {"foo1": "bar3", "foo2": "bar2"}](
        HEADERS < "Server"  # ключ Server содержится в заголовках
        , HEADERS["Server"] == "cloudflare"  # проверка значения ключа Server (обращение к ключу объекта)
        , HEADERS.Server == "cloudflare"     # тоже самое, но через обращение к атрибуту
    )
    
    , browser="http"
    , test_id="get_param"
)

CONTENT | CONTENT(запрос, [ cached ])

Возвращает тело ответа сервера. Может быть использована вне описания запроса, в этом случае первым аргументом нужно передать объект запроса у которого нужно получить тело ответа.

Аргумент cached может принимать следующие значения: True, False и None. Данные в любом случае будут возвращены из кэша, но True означает что возвращаемый результат будет взят только из кэша. False - что будет выполнен запрос к серверу, а полученный результат будет закэширован. None - если значение заголовка Cache-Control будет равно no-cache, то кэш будет инвалидирован (т.е. поведение аналогично значению False) иначе нет.

Аргументы:

  • Запрос - Объект запроса для которого нужно вернуть тело ответа.
  • cached - Режим инвалидации кэша (описан выше).

Пример:

# запрос получения списка книг текущего пользователя
books = GET["/books/all_books"](
    STATUS == STATUS.OK
    , CHECK_JSON_SHEMA("api/shema/books/all_books.json")
)
# получаем список всех ISBN
isbn = CONTENT(books)["books"]["isbn"]

TEST["Все книги"](
    "В коллекции книг есть книги у которых определён ISBN"
    , COUNT(isbn) > 0
)

PAYLOAD(body)

Добавляет данные в тело запроса. Если атрибут запроса content_type равен JSON, то в качестве тела запроса должен быть передан словарь, иначе текстовые данные.

Аргументы:

  • body - Тело запроса.

Пример:

TEST["Добавляем книгу в коллекцию пользователя"](
    POST["/user/books"](
        STATUS == 201
        , PAYLOAD({
            "userId": "scope::api/user_id"
            , "collectionOfIsbns": [{"isbn": "978-5-699-12014-7"}]
    }))
    
    , tags="api"
)

HEADER_SET(заголовок=значение)

Добавляет заголовок в запрос.

Аргументы:

  • заголовок - Наименование заголовка.
  • значение - Значение заголовка.

Пример:

TEST["Параметры GET запроса"](
    GET["https://postman-echo.com/get", {"foo1": "bar3", "foo2": "bar2"}](
        HEADER_SET(hlp=5, hlp2=3)  # устанавливаем заголовки "hlp" и "hlp2"
        , CONTENT["headers"].hlp == 5  # тело ответа содержит все переданные заголовки 
        , CONTENT.headers["hlp2"] == 3 # по этому мы можем проверить их значение через объект CONTENT
))

Аутентификация

AUTH_BEARER(access_token)

Добавляет токен для аутентификации через JWT-токены.

Аргументы:

  • access_token - Токен для аутентификации.

Пример:

# объект запроса получения токена
get_token = POST["/account/get_token"](
    STATUS == STATUS.OK
    , PAYLOAD({"user_name": "Meta", "password": "Test"})
)

TEST["Проверка запроса одной книги"](
    AUTH_BEARER(CONTENT(get_token)["token"])  # получаем и устанавливаем ключ аутентификации, он будет действовать весь тест
    , POST["/books/book", {"isbn": "9785699120147"}](
        STATUS == 200
        , CHECK_JSON_SHEMA("api/shema/books/one_book.json")
))

AUTH_BASE(user, passwd)

Команда реализует базовую аутентификацию.

Аргументы:

  • user - Логин пользователя.
  • passwd - Пароль пользователя.

Пример:

TEST["Базовая авторизация"](
    AUTH_BASE("postman", "password")
    , GET["https://postman-echo.com/basic-auth"](
        STATUS == STATUS.OK
        , CONTENT["authenticated"] == True
))

Триггеры и аутентификация

Для аутентификации можно использовать триггеры. В примере приведённом ниже:

  • создаётся тестовый пользователь (метод setup)
  • перед запуском каждого теста производится авторизация при помощи команды AUTH_BEARER (метод setup_test)
  • после завершения всех тестов удаляется тестовый пользователь (метод close)

Пример:

token = {"user": "Meta", "passwd": "Test"}

make_token = POST["/account/get_token"](
    STATUS == STATUS.OK
    , CHECK_JSON_SHEMA("api/shema/token.json")
    , PAYLOAD(token)
)

del_user = DELETE["/account/user/{ 0 }"](
    STATUS == STATUS.OK
)

class AuthTrigger(BaseTrigger):
    def setup(self):
        return (
            "Создаём тестового пользователя"
            , POST["/account/user"](
                STATUS > {STATUS.CREATED, STATUS.NOT_ACCEPTABLE}
                , PAYLOAD(token)
        ))
    
    def setup_test(self, browser, test_id, test_scope, test_args):
        # Авторизация пользователя
        return AUTH_BEARER(CONTENT(make_token).token)
    
    def close(self):
        return (
            "Удаляем тестового пользователя"
            , AUTH_BEARER(CONTENT(make_token)["token"])
            , del_user(CONTENT(make_token)["userId"])
        )

CONFIG.TRIGGER = AuthTrigger

Для версии 2.0 редакция от 16.09.2026


Группа в Max |  Группа в Telegramm
Политика конфиденциальности
© ИП Пуляев Григорий Васильевич, 2024