Всем привет. Мы потихоньку выходим из тени и продолжаем серию статей о нашем продукте. После предыдущей обзорной статьи мы получили множество отзывов (преимущественно положительных), предложений и bug репортов. Сегодня мы покажем TestMace в деле и вы по достоинству сможете оценить некоторые фишки нашего приложения. Для более полного погружения советую обратиться к нашей документации по адресу http://docs-ru.testmace.com. Итак, поехали!
Установка
Начнем с банальщины. Приложение доступно и реально тестируется на трех платформах — Linux, Windows, MacOS. Вы можете скачать установщик для интересующей ОС с нашего сайта. Для линуксоидов есть возможность установки snap пакета. Очень надеемся, что скоро дойдут руки и до Microsoft Store и App Store (А надо ли? Как думаете?).
Подопытный сценарий
В качестве испытуемого мы выбрали следующий стандартный сценарий:
- залогинимся: пользователь — admin, пароль — password
- добавим новую запись
- проверим корректное добавление записи
Тестировать будем на https://testmace-quick-start.herokuapp.com/. Это обычный json-server, прекрасно подходящий для тестирования подобных приложений. Мы только добавили авторизацию по токену на все роуты json-server-а и сделали метод login для получения этого самого токена. Двигаться будем поступательно, постепенно усовершенствуя наш проект.
Создание проекта и попытка создать сущность без авторизации
Для начала создадим новый проект (File->New project). Если вы запускаете приложение впервые, то новый проект откроется автоматически. Для начала попробуем сделать запрос на создание новой записи (вдруг создание записей доступно без авторизации). Выберите в контекстном меню Project узла пункты Add node -> RequestStep. В качестве имени узла зададим create-post. В результате в дереве создастся новый узел и откроется вкладка данного узла. Зададим следующие параметры запроса:
- Тип запроса: POST
- url: https://testmace-quick-start.herokuapp.com/posts
- Тело запроса: json со значением
{"title": "New testmace quick start post"}
Если вы все сделали правильно, то интерфейс будет выглядеть следующим образом:
Однако если мы попробуем выполнить запрос, то сервер возвратит 401 код и без авторизации нам на этом сервере ничего не светит. Ну, в общем-то, ожидаемо).
Добавляем запрос на авторизацию
Как уже было сказано, у нас есть POST endpoint /login
, который принимает в качестве тела запроса json вида: {"username": "<username>", "password": "<password>"}
, где username
и password
(опять таки, из вводной выше) имеют значения admin
и password
соответственно. В ответ данный endpoint возвращает json вида {"token": "<token>"}
. Воспользуемся им для авторизации. Создадим RequestStep узел с именем login, в качестве предка будет выступать Project узел. С помощью drag-and-drop переместите данный узел в дереве выше, чем узел create-post. Зададим вновь созданному запросу следующие параметры:
- Тип запроса: POST
- url: https://testmace-quick-start.herokuapp.com/login
- Тело запроса: json со значением
{"username": "admin", "password": "password"}
Выполним запрос и получим двухсотый код с токеном в ответе. Как-то так:
Рефакторинг: убираем дублирование домена
Пока запросы не связаны в единый сценарий. Но это не единственный недостаток. Если присмотреться, то можно заметить, что как минимум домен дублируется в обоих запросах. Нехорошо. Самое время отрефакторить эту часть будущего сценария и в этом нам помогут переменные.
В первом приближении переменные выполняют ту же самую роль, что и в других подобных инструментах и языках программирования — устранение дублирования, повышение читабельности и т.д. Подробнее о переменных можно почитать в нашей документации. В данном случае нам понадобятся пользовательские переменные.
Определим на уровне Project узла переменную domain
со значением https://testmace-quick-start.herokuapp.com
. Для этого необходимо
- Открыть вкладку с данным узлом и нажать на иконку калькулятора справа вверху
- Нажать на + ADD VARIABLE
- Ввести имя и значение переменной
В нашем случае диалог с добавленной переменной будет выглядеть следующим образом:
OK. Теперь за счет наследования мы можем использовать данную переменную в потомках любого уровня вложенности. В нашем случае это узлы login и create-post. Для того, чтобы в текстовом поле использовать переменную, необходимо написать ${<variable_name>}
. Например, url для логина преобразуется в ${domain}/login
, соответственно для create-post узла url будет выглядеть как ${domain}/posts
.
Таким образом, руководствуясь принципом DRY, мы немного улучшили сценарий.
Сохраняем токен в переменную
Раз уж зашел разговор о переменных, давайте немного разовьем эту тему. На данный момент мы в случае успешного логина получаем от сервера авторизационный токен, который потребуется нам в последующих запросах. Давайте сохраним этот токен в переменную. Т.к. значение переменной будет определяться во время выполнения сценария, используем для этого специальный механизм — динамические переменные.
Для начала выполним запрос на логин. Во вкладке Parsed ответа наведите курсор на токен и в контекстном меню (которое вызывается либо правой кнопкой мыши, либо нажатием на кнопку ...) выберите пункт Assign to variable. Появится диалог со следующими полями:
- Path — какой кусок ответа берется (в нашем случае это
body.token
) - Current value — какое значение лежит по пути Path (в нашем случае это значение токена)
- Variable name — название переменной, куда Current value будет сохраняться. В нашем случае это будет
token
- Node — в каком из предков будет создана переменная Variable name. Выберем Project
Заполненный диалог выглядит следующим образом:
Теперь при каждом выполнении узла login динамическая переменная token
будет обновляться новым значение из ответа. И эта переменная будет храниться в Project узле и благодаря наследованию будет доступна потомкам.
Для того, чтобы обратиться к динамическим переменным, необходимо использовать встроенную переменную $dynamicVar
. Например, чтобы достучаться до сохраненного токена, необходимо вызвать ${$dynamicVar.token}
.
Прокидываем авторизационный токен в запросы
На предыдущих шагах мы получили авторизационный токен и все, что нужно сделать, это добавить заголовок Authorization
со значение Bearer <tokenValue>
во все запросы, требующие авторизации, в том числе и в create-post. Для этого есть несколько способов:
- Вручную скопировать токен и добавить авторизационный заголовок в интересующие запросы. Способ рабочий, однако его применение ограничивается только запросами вида "сделал и выкинул". Для многократного выполнения сценариев не подойдет
- Воспользоваться функционалом авторизации.
- Использовать заголовки по умолчанию
Использование второго способа кажется очевидным, однако в контексте данной статьи такой подход… неинтересен. Ну в самом деле: механизм авторизаций плюс минус знаком вам из других инструментов (пусть у нас и имеются штуки вроде наследования авторизаций) и вряд ли вызовет вопросы.
Другое дело заголовки по умолчанию! Если в двух словах, то заголовки по умолчанию — это наследуемые от предков HTTP-заголовки, которые по умолчанию добавляются к запросу, если их явно не отключить. С помощью данного функционала можно к примеру, реализовать кастомную авторизацию или просто избавиться от дублирования в сценариях. Применим данную фичу для прокидывания токена в заголовках.
Ранее мы предусмотрительно сохранили токен в динамическую переменную $dynamicVar.token
на уровне Project узла. Остается сделать следующее:
- Определить заголовок по умолчанию
Authorization
со значениемBearer ${$dynamicVar.token}
на уровне Project узла. Для этого в интерфейсе Project узла необходимо открыть диалог с заголовками по умолчанию (кнопка Headers в правом верхнем углу) и добавить соответствующий заголовок. Диалог с заполненными значениями будет выглядеть следующим образом:
- Выключить данный заголовок из login запроса. Это и понятно: на момент логина у нас еще нет токена и мы этим запросом как раз таки установим его. Поэтому в интерфейсе login запроса во вкладке Headers в области Inherited уберем галочку с Authorization заголовка.
На этом все. Теперь заголовок авторизации будет добавляться во все запросы, являющиеся потомками Project узла, кроме login узла. Получается, что на данном этапе у нас уже готов сценарий и нам остается это только запустить. Запустить сценарий можно, выбрав пункт Run в контекстном меню Project узла.
Проверяем корректность создания поста
На данном этапе наш сценарий умеет логиниться, и, используя авторизационный токен, создавать пост. Однако нам необходимо удостовериться, что вновь созданный пост имеет корректное имя. То есть по сути остается сделать следующее:
- Отправить запрос на получение поста по id,
- Проверить, что имя, пришедшее с сервера, соответствует имени, переданному при создании поста
Рассмотрим первый шаг. Раз значение id определяется во время выполнения скрипта, необходимо создать динамическую переменную (назовем ее postId
) из узла create-post на уровне Project узла. Как это сделать мы уже знаем, достаточно обратиться к разделу Сохраняем токен в переменную. Остается только создать запрос на получение поста по данному id. Для этого создадим RequestStep get-post со следующими параметрами:
- Тип запроса: GET
- URL: ${domain}/posts/${$dynamicVar.postId}
Для реализации второго шага нам необходимо познакомиться с Assertion узлом. Assertion узел — это узел, позволяющий писать проверки на определенные запросы. Каждый Assertion узел может содержать несколько утверждений (проверок). Подробнее обо всех видах assertion-ов вы сможете прочитать из нашей документации. Мы будем использовать Compare
assertion с оператором equal
. Есть несколько способов создания assertion-ов:
- Долгий. Вручную из контекстного меню RequestStep узла создать Assertion узел. В созданном Assertion узле добавить интересующий assertion и заполнить поля.
- Быстрый. Создать Assertion узел вместе с assertion-ом из ответа RequestStep узла с помощью контекстного меню
Воспользуемся вторым способом. Вот как это будет выглядеть для нашего кейса.
Для тех кто не понял, тут происходит следующее:
- Сделать запрос в узле get-post
- Во вкладке Parsed ответа вызвать контекстное меню и выбрать Create assertion -> Compare -> Equal
Поздравляю, мы создали первый тест! Просто, не правда ли? Теперь можете запустить сценарий полностью и наслаждаться результатом. Остается совсем чуть-чуть отрефакторить и вынести title
в отдельную переменную. Но мы оставим это вам в качестве домашнего задания)
Заключение
В данном руководстве мы создали полноценный сценарий и заодно провели обзор некоторых фич нашего продукта. Разумеется, мы воспользовались далеко не всем функционалом и в следующих статьях мы проведем детальный обзор возможностей TestMace. Следите за обновлениями!
P.S. Для тех, кому лень воспроизводить все шаги, мы любезно запилили репозиторий с проектом из статьи. Открыть его можно с помощью File -> Open project и выбрать папку Project.
Автор: Дмитрий Сныткин