Автор: Надежда Дудник

Памятка для инженеров по тестированию ПО.

Продолжаю серию своих статей про Insomnia, первую статью можно прочитать по ссылке.

Сейчас хочу поделиться разбором динамических переменных и показом примера скриптов с использованием Chains.

Введение

Insomnia - инструмент для тестирования API (клиент взаимодействия с API).

Для примера я буду использовать сайт Vikunja и еще другие примеры.

UI: https://try.vikunja.io/login

API documentation: https://try.vikunja.io/api/v1/docs

Скачать готовую коллекцию для данного сайта, которую составляли по написанным тест-кейсам API в рамках статьи.

На момент написании статьи используется версия Insomnia: 8.6.0 для Windows.

Base Environment

Начну показывать переменные через созданное окружение "Vikunja Environment".

Всевозможные переменные

Структуру переменных для сайта Vikunja можно выстроить в формате JSON.

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

Переменные для сайта Vikunja в Manage Environments (композиция переменных в JSON структуре)
{
	"hosts": {
		"base_URL": "https://try.vikunja.io/api/v1",
		"sm_URL": ""
	},
	"headers": {
		"content-type": "application/json"
	},
	"users": {
		"username": "Nadezhda_test1",
		"email": "user_testing1@test.com",
		"password": "Qq1234568"
	},
	"auth": {
		"Token": "Response -> Body Attribute"
	},
	"projects": {
		"project_Id": "Response -> Body Attribute",
		"title": "project_title",
		"hex_color": "7f23ff"
	},
	"tasks": {
		"task_Id": "Response -> Body Attribute",
		"title_task": "title_task"
	},
	"labels": {
		"label_Id": "Response -> Body Attribute"
	}
}

Напоминаю, чтобы выбрать переменную из окружения, например, в адресной строке, нужно указать  _.

Отображение _.hosts.base_URL в строке запроса (или выбираем через  _.)

Динамические переменные

Динамические переменные в Insomnia
+ еще переменные
Переменные из Response и Request
Переменные из Request

Разберу несколько из выше показанных переменных.

Чтобы отобразился список переменных, важно указать начало поиска, например, чтобы найти "UUID" переменную для ключа достаточно ввести "u", и затем отобразится список переменных, где встречается буква "u".

Данные переменные можно генерировать не только через окружения,

Объявление динамических переменных через окружение

но и через тело ответа запроса, а также их объявлять в теле запроса и в заголовках запроса.

Пример1: Объявление динамических переменных в теле запроса
Пример2: Объявление динамических переменных в теле запроса

еще пример:

Объявление динамических переменных в заголовках запроса

Значение переменной можно увидеть, нажав на данную выбранную переменную, и откроется всплывающее окно "Edit Tag".

  1. UUID -> Version - генерация UUID - значения

    uuid
  2. Timestamp - get the current time

    timestamp
  3. Base64 - encode or decode values - для URL

  4. OS - get OS info - всевозможные функции

    Характеристика OS
  5. Использование JSONPath

    Определение значения из JSON string
  6. Hash - apply hash to a value для Base64

  7. Из ответа от сервера Response можно "вытащить" следующие значения:

    • Значение из тела ответа от сервера

    • Тело ответа от сервера

    • Значение заголовка из ответа сервера

    • URL-адрес инициирующего запроса

  8. Из запроса Request можно "вытащить" следующие значения:

    1. Например, Значение заголовка из запроса

    2. Значение Cookie по названию

      и т.д..

      Также отдельно есть прочтение содержимого из файла, использование входных данных для пользователя. Я разобрала те переменные, которые часто используются в работе, особенно используется "Body Attribute - value of response body"

Вкладка Tests -> New Test Suite -> New Test

Примеры скриптов для регистрации пользователя для сайта Vikunja c использованием chaijs

Написание скриптов для запроса регистрации пользователя на вкладке Tests
//отправка запроса POST /register
const response2 = await insomnia.send('req_0ca37b8e2a0f40a7a610250ef48f4697'); 

// проверка статус кода
expect(response2.status).to.equal(200) 

//парсинг тела ответа от сервера на язык js
const res_body = JSON.parse(response2.data)

//отображение тела ответа от сервера в консоли
console.log(res_body)

//тело ответа от сервера является объектом
expect(res_body).to.be.an('object')

//значение ключа username является строкой
expect(res_body.username).to.be.a('string')

//ключ username не пустой
expect(res_body.username).not.has.length(0)

//значение ключа email является строкой
expect(res_body.email).to.be.a('string')

//значение ключа email не пустой
expect(res_body.email).not.has.length(0)

//Проверка, что у объекта есть ожидаемые поля
const expected_keys = [
	"id",
	"name",
	"username",
	"email",
	"created",
	"updated"
]

//Проверка ожидаемых ключей в теле ответа от сервера
expect(res_body).to.have.all.keys(expected_keys)

//Проверка того, ключи в ответе от сервера равны какому-то значению
expect(res_body.username).to.equal("<Указать значение из окружения>")
expect(res_body.email).to.equal("<Указать значение из окпужения>")

Хочу отметить, что можно выбрать запрос через "Select a request", а можно отправить запрос внутри самого теста.

Например, я указываю так:

Отправка запроса внутри теста вместо поля “Select a request”

Примеры скриптов для авторизации пользователя

//отправка запроса POST /login
const response2 = await insomnia.send('req_c6319e16d41a4ed593fec04d92f7183c');

// проверка статус кода
expect(response2.status).to.equal(200);

const res_body = JSON.parse(response2.data)
console.log(res_body)

//тело ответа от сервера является объектом
expect(res_body).to.be.an('object')

//значение ключа token является строкой
expect(res_body.token).to.be.a('string')

//значение ключа token не пустое
expect(res_body.token).not.has.length(0)
console.log(res_body.token)

//можно комбинировать проверку через .and
expect(res_body.token).to.be.a('string').and.not.has.length(0)

Примеры скриптов для создания проекта пользователем на сайте (Create Project)

//отправка запроса PUT /projects
const response2 = await insomnia.send('req_b8be8c6b91e24343af7e2c1ae1ffa7fc');

// проверка статус кода 201
expect(response2.status).to.equal(201);

const res_body = JSON.parse(response2.data)
console.log(res_body)

//тело ответа от сервера является объектом
expect(res_body).to.be.an('object')

//тело ответа имеет свойство (ключ) id
expect(res_body).to.have.property('id')

//значение ключа id является числом
expect(res_body.id).to.be.a('number')

//gроверка того, ключ в ответе от сервера равен какому-то значению
expect(res_body.id).to.equal(<Указать ожидаемое значение>)
console.log(res_body.id)

//значение ключа title является строкой
expect(res_body.title).to.be.a('string')

//провекра указана с комментарием, в случае если owner.username не будет являться строкой
expect(res_body.owner.username, "поле username должно быть строкой").to.be.a('string')

//значение ключа is_archived является boolean
expect(res_body.is_archived).to.equal(false)

Примеры скриптов для получения всех проектов Get all Projects

//отправка запроса GET /projects
const response2 = await insomnia.send('req_716ace9255e34ac1970bfc7571dc6ab0');

//проверка статус кода 200
expect(response2.status).to.equal(200);

const res_body = JSON.parse(response2.data)

//объявление константы для элемента в массиве
const project_id1 = res_body[0].id
console.log(project_id1)

//для примера - и то эксперимент
const expected_colors = ["7f23ff"]

//в JavaScript есть метод map для списков, применяющий функцию => к каждому из его элементов
//проверка только необходимого ключа
const actual_colors = res_body.map(item => item.hex_color)

//проверка, что есть ключ, заполненный определенным значением
expect(actual_colors).to.include.members(expected_colors)
console.log(actual_colors)

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

//просто пример
const values = [{"hex_color": "7f23ff", "title": "project_title"}, {"hex_color": "7f23f0", "title": "project_title2"}, {"hex_color": "7f32ff", "title": "project_title3"}]]]
const expected_values = [{"hex_color": "7f23ff", "title": "project_title"}]
expect(values).to.include.deep.members(expected)

//проверить имеющиеся ожидаемые ключи
const keys = {"hex_color": "7f23ff", "title": "project_title"}
const expected_keys = ["hex_color", "title"]
expect(keys).to.include.all.keys(expected_keys)

//в JavaScript есть Set для уникальных значений
//проверка необходимого ключа hex_color
const hex_colors = ["7f23ff", "7f23fs", "7f05ff","7f23ff"]
const unique_colors = new Set(hex_colors)
expect(unique_colors).to.have.lengthOf(3)
expect(unique_colors).to.have.all.keys("7f23ff", "7f23fs", "7f05ff")

//есть еще метод forEach - цикл - по каждому элементу 
//и метод .filter для фильтрации значений

Из https://www.chaijs.com/api/bdd/ и https://docs.insomnia.rest/insomnia/unit-testing можно использовать различные конструкции, чтобы составить свои проверки на вкладке tests.

Заключение

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

Также я предлагаю просмотреть мой вебинар на тему "Тестирование API с использованием Insomnia"

Благодарю за просмотр и прочтение.

С уважением, Надежда Дудник (protestinginfo), главный инженер по тестированию в финтехе и ментор по тестированию ПО.

И желаю достичь своей цели!