Script

Узел, выполняющий сценарии, написанные на JavaScript. Script будет полезен для решения разных задач:

  • Реализация сложных тестов над результатами одного или нескольких других узлов

  • Генерация тестовых данных

  • Преобразование переменных других узлов

  • Выполнение операций для приведения тестируемой системы в заданное состояние (set_up, tear_down)

  • Отладка и доступ к состоянию всех узлов проекта

Редактирование

Окно редактирования узла разделено на две области - окно редактирования кода и окно консольного вывода. Для скрытия консоли нажмите на кнопку .

Над окном консольного вывода расположена панель инструментов для управления поведением консоли:

  • / - переключение между режимами сохранения результатов выполнения в консоли. - очистка консоли перед каждым запуском скрипта, - накопление результатов запуска.

  • - автоматическая прокрутка к последней строке вывода консоли

  • - очистить текущий вывод консоли

Запуск

Скрипт начинает выполнение при нажатии на кнопку RUN. Узел заканчивает свое выполнение после исполнения всех строки кода и после завершения всех асинхронных задач (например, setTimeout). Скрипт считается выполненным успешно при выполнении следующих условий:

  • В коде не выявлено синтаксических ошибок

  • При выполнении все выброшенные исключения обработаны

  • Выполнение заняло не более 30 секунд (по истечении этого времени скрипт будет прерван)

Вызов скрипта обернут в функцию, поэтому для того, чтобы прервать выполнение без ошибок воспользуйтесь инструкцией возврата: return;

Чтобы прервать выполнения скрипта с ошибкой, воспользуйтесь выбросом любого исключения: throw new Error('Something went wrong');

Библиотеки

Запуск осуществляется в виртуальном окружении node.js. Пользователю доступно некоторые модули из node.js, а также все встроенные возможности JavaScript, поддерживаемые движком V8.

Осуществляется поддержка стандарта ECMAScript 6

Доступные модули из node.js

  • fs - работа с файловой системой

Доступные сторонние модули

  • lodash - библиотека со множеством утилитарных алгоритмов

  • moment.js - библиотека для работы с датами

  • CryptoJS - библиотека реализующая множество криптографических алгоритмов

  • random-js - библиотека для генерации математически корректных случайных чисел

  • faker.js - библиотека для генерации случайных данных для свойств различных сущностей

  • chai.js - библиотека предоставляющая комфортные интерфейсы для проверки логических утверждений.

  • request - библиотека предоставляющая простой в использовании HTTP-клиент.

Контекст выполнения

Ниже приведены объекты и функции глобальной области видимости скрипта.

Доступ к сторонним модулям

Все описанные модули автоматически подключаются к контексту выполнения и доступны в глобальной области видимости.

lodash

const chunks = _.chunk([1, 2, 3, 4], 2);

moment.js

const now = moment();

CryptoJS

const hash = crypto.MD5('Message');

random-js

const randomEngine = new random.Random();
const shuffledArray = randomEngine.shuffle([1,2,3,4,5]);

faker.js

const person = {
'name': faker.name.findName(),
'email': faker.internet.email()
};

chai.js

const foo = 'bar';
// success
assert.equal(foo, 'bar');
expect(foo).to.equal('bar');
// failure
assert.equal(1, 0);

request

request('https://docs-ru.testmace.com', (error, response, body) => {
assert.equal(error, null);
assert.equal(response.statusCode, 200);
assert.notEqual(body, null);
finish();
});

console.*

Методы для вывода данных в консоль: log, info, warn, error, debug, exception

Сигнатура методов совпадает с их стандартными версиями. Каждый тип события в консоли окрашивается в свой цвет. Каждая строка сопровождается указателем на строку и столбец, из которой произошел вызов функции вывода. События типа exception отображаются вместе со стеком вызовов внутри скрипта.

Асинхронный код

Скрипт может содержать асинхронные вызовы (например, Promise, setTimeout, addEventListener, колбэки при вызове встроенных модулей и пр.). В некоторых случаях мы можем определить, когда асинхронный код выполнен и понять, что скрипт завершен. Чтобы явно сообщить об окончании работы скрипта, нужно добавить вызов встроенной функции finish() . При передачи массива объектов типа Error, то скрипт завершится с ошибкой и отобразит переданные ошибки в консоли. На работу скрипта отводится максимум 30 секунд, по истечению которых скрипт завершится с ошибкой.

Пример использования функции finish()

request('https://docs-ru.testmace.com', (error, response, body) => {
console.log(body);
error ? finish([error]) : finish();
});

В глобальной области видимости доступен объект для доступа к проекту и текущему Script узлу - tm.

tm

  • currentNode: nodeAPI - интерфейс текущего Script узла

  • project: nodeAPI - интерфейс узла проекта

  • env: envAPI - интерфейс для доступа к переменным окружения проекта

  • cookies: cookie[] - список установленных в проекте cookies

  • systemVars: object - объект, содержащий переменные окружения системы

nodeAPI

  • parent: nodeAPI - возвращает интерфейс для родительского узла. Для узла проекта значение будет null

  • name: string - имя данного узла

  • type: string - тип данного узла.

  • path: string - путь до данного узла, относительно корня проекта.

  • children: nodeAPI[] - список интерфейсов дочерних узлов

  • findChild(name: string): nodeAPI - поиск дочернего узла по его `name`. Если узел с таким именем не найдет, вернется null

  • next: nodeAPI - интерфейс следующего по порядку узла в группе. Если текущий узел является последним, то вернется null

  • prev: nodeAPI - интерфейс предыдущего по порядку узла в группе. Если текущий узел является первым в группе, то вернется null

  • nextNodes: nodeAPI[] - список всех узлов в группе следующих за текущим. Если текущий узел является последним, то вернется пустой список

  • prevNodes: nodeAPI[] - список всех узлов в группе предшествующих текущему. Если текущий узел является первым по порядку, то вернется пустой список

  • vars: object - объект, содержащий все статические переменные данного узла

  • dynamicVars: object - объект, содержащий все динамические переменные данного узла.

  • setDynamicVar(name: string, value: any): void - метод устанавливает динамическую переменную `name` cо значением `value` для данного узла.

requestNodeAPI

Узел типа RequestStep обладает расширенным интерфейсом.

  • request: object - объект содержит настройки запроса узла.

  • response: object - объект содержит результаты последнего выполнения запроса

envAPI

  • active: string - имя активного окружения

  • vars: object - объект содержит переменные текущего окружения

Примеры

Рекурсивный обход потомков узла

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

const current = tm.currentNode;
const parent = current.parent;
if (!parent) {
console.warn(`Parent of ${current.path} not found`);
return;
}
const value = parent.vars['ID'];
if (!value) {
console.warn(`Node ${parent.path} hasn't have value for ID`);
return;
}
console.log(`Parent ID = ${value}`);
const setIDToNode = (node) => {
node.setDynamicVar('ID', value);
};
const traverseDescendants = (node, func, depth) => {
node.children.forEach((child) => {
func(node);
indent = '\t'.repeat(depth);
console.debug(
`${indent}${child.path}`,
`${indent}Value: ${child.dynamicVars['ID']}`
);
traverseDescendants(child, func, depth+1);
});
};
traverseDescendants(parent, setIDToNode, 0);

Поиск узлов по имени

В данном примере демонстрируется как можно найти дочерний узел по его имени при помощи метода findChild

const current = tm.currentNode;
const scriptNode = current.parent.findChild(current.name);
assert.equal(current, scriptNode);

Генерация и сохранение данных в переменные

В данном примере мы генерируем случайную строку-идентификатор при помощи библиотеки faker и устанавливаем ее следующему узлу как динамическую переменную UUID. После выполнения скрипта из следующего узла можно сослаться на данную переменную в URL, теле запроса и т.п.

const current = tm.currentNode;
const uuid = faker.random.uuid();
const anotherNode = current.next;
anotherNode.setDynamicVar('UUID', uuid);

Файловое представление

{
"type": "object",
"properties": {
"type": {
"description": "Type of Script node",
"const": "Script",
"type": "string"
},
"script": {
"description": "Javascript code",
"type": "string"
},
"children": {
"description": "List of children names",
"type": "array",
"items": {
"type": "string"
},
"default": []
},
"variables": {
"$ref": "#/definitions/NodeVariables",
"description": "Node variables dictionary"
},
"name": {
"description": "Node name",
"type": "string"
}
},
"required": [
"children",
"name",
"script",
"type",
"variables"
],
"definitions": {
"NodeVariables": {
"type": "object",
"additionalProperties": {
"type": "string"
}
}
},
"$schema": "http://json-schema.org/draft-07/schema#"
}