Сделайте легкую работу по автоматизации тестирования QA для всех ваших конечных точек с Flagpole JS.

Приятно работать в такой компании, как FloSports, которая, как правило, поддерживает сообщество разработчиков ПО с открытым исходным кодом. У меня были проблемы с существующими тестовыми платформами, которые на мой вкус были слишком медлительными. Поэтому в качестве побочного проекта я решил создать простой и молниеносный QA-пакет. Он написан на TypeScript и работает на движке Node.

Пакет был опубликован на NPM с лицензией MIT.

Его можно запускать в Терминале с помощью встроенного инструмента командной строки, интегрировать вручную в ваше приложение, запускать по расписанию на сервере или Lambda или привязать к вашим хукам Git или Jenkins как часть автоматизации до или после развертывания.

В этой статье я просто углублюсь в код, чтобы дать быстрые примеры того, как начать. Он должен помочь вам сразу же изучить основы тестирования вашего REST API.

Начиная

Прежде всего, давайте установим интерфейс командной строки Flagpole глобально с помощью этой команды:

npm i -g flagpole

Если у вас уже есть проект, в котором вы хотите его запустить, перейдите в эту папку и проигнорируйте следующий шаг. Предполагая, что вы хотите сделать это автономно:

mkdir flagpole-example
cd flagpole-example
npm init

Теперь установите, нам нужно установить Flagpole в нашем проекте. Да, это избыточное ощущение, но оно необходимо.

npm i flagpole

Здорово! Теперь библиотека доступна в нашем проекте. Давайте инициализируем наш проект Flagpole. Это создаст для нас необходимый файл конфигурации и папку.

flagpole init

Команда задаст вам несколько вопросов, и тогда все будет готово. После этого давайте сделаем еще одну команду, чтобы добавить наш первый набор.

flagpole add suite

Он задаст вам ряд вопросов. Заполните их вот так.

  • Название пакета: itunes
  • Описание Suite: iTunes API Test
  • Первый сценарий: поиск музыкальных видеоклипов
  • Тип теста: REST API (формат JSON)
  • Базовый домен: https://itunes.apple.com (он запросит у вас домен для каждой среды, которую вы указали в команде init)
  • Начальный путь сценария: / search? Term = 2pac & entity = musicVideo

Это должно было создать для вас файл набора тестов в папке тестов с именем itunes.js с этим кодом в нем:

const { Flagpole } = require('flagpole');
const suite = Flagpole.Suite('iTunes API Test')
    .base('https://itunes.apple.com');
suite.Scenario('Music Videos Search')
    .open('/search?term=2pac&entity=musicVideo')
    .json()
    .assertions(function (response) {
    });

Итак, что мы здесь сделали, так это импортировали модуль Flagpole, определили тест под названием «iTunes API Test» и определили единственный сценарий в этом наборе для конечной точки поиска с некоторыми параметрами. Установка типа json также важна, потому что в противном случае мы будем в тестовом режиме HTML (который предназначен для всей другой учебной статьи).

На самом деле мы еще не определили какие-либо конкретные утверждения, но это нормально. Этот тест уже будет запущен и должен пройти. Flagpole пытается облегчить вашу жизнь, вводя тесты без вашего написания, поэтому он добавит проверку, что конечная точка загружена нормально и что ответ JSON был действительным.

Давайте попробуем это с помощью команды запуска:

flagpole run

Как он узнал, что бежать? Вот почему мы настроили файл конфигурации ранее. Эта простая команда запустит все наборы тестов, которые она найдет в этой папке (и любых других вложенных папках в ней).

Результат должен выглядеть так:

Теперь давайте добавим пару простых тестов в метод утверждений нашего сценария. Давайте удостоверимся, что код состояния HTTP равен 200 и что запрос API вернулся менее чем за 1000 миллисекунд.

response.status().equals(200);
response.loadTime().lessThan(1000);

Теперь наш запуск флагштока должен выглядеть следующим образом:

Ответ от iTunes API имеет свойство resultsCount, а фактические данные находятся в массиве объектов, называемых results. Итак, что мы теперь хотим сделать, это проверить, что счетчик больше 0 и что счетчик соответствует фактической длине количества элементов в массиве результатов.

Вот наш код для этого:

let count = response.select('resultCount')
    .greaterThan(0)
    .get();
response.select('results').length().equals(count);

Итак, это вводит несколько новых концепций. Сначала мы видим метод select, который мы можем использовать для обхода ответа JSON для выбора определенного элемента. Затем мы запускаем на нем утверждение betterThan. После этого мы используем метод get для возврата фактического значения, чтобы оно было сохранено в переменной count для использования в следующей строке.

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

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

Мы снова видим, что Flagpole создал для нас пару дополнительных тестов. Каждый раз, когда мы выбирали данный элемент, он добавлял утверждение существует. И мы также видим, что наше количество и длина совпадают, как мы и ожидали.

А теперь давайте посмотрим на провал. Давайте выберем несуществующий элемент foobar и посмотрим, что произойдет.

response.select('foobar');

Наши выходные данные о запуске флагштока теперь показывают проблему:

Нет проблем, потому что мы тоже можем проводить отрицательные тесты. Если мы хотим убедиться, что этот элемент НЕ существует, мы просто переворачиваем утверждение, вызывая метод not () непосредственно перед ним.

response.not().select('foobar');

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

Вы можете использовать этот метод not () с любым утверждением (или подразумеваемым утверждением, как указано выше), и он изменит ожидаемый результат.

А теперь займемся чем-нибудь более интересным. Давайте проверим, что результаты поиска - это то, что мы действительно искали. Мы указали, что сущность в параметрах запроса была musicVideo. В iTunes API это соответственно ограничивает эти результаты. Так что было бы плохо, если бы мы вернули какой-нибудь результат, кроме музыкального клипа.

response
    .select('results')
    .label('Make sure every response is a track and a music video')
    .every(function (result) {
        return result.property('kind').toString() == 'music-video';
    });

Итак, мы на самом деле представили здесь несколько новых вещей. Сначала вы обратите внимание на метод метки. Это позволяет нам заменить сообщение о прохождении / отказе по умолчанию для следующего утверждения. Иногда стандартные сообщения - это нормально, но иногда было бы неплохо иметь удобочитаемый текст, объясняющий, что мы делаем.

Тогда вы видите, что мы сделали каждое утверждение. Обратному вызову передается аргумент для каждого дочернего элемента в выбранном массиве. В конечном итоге нам нужно вернуть логическое значение из этого обратного вызова. Утверждение проходит только в том случае, если каждая итерация этого цикла вернула истину.

Обратите внимание, что мы использовали метод toString () для получения значения из свойства kind каждого результата. Это позволило нам провести прямое логическое сравнение со строкой music-video, чего мы ожидаем от каждой строки. Очевидно, здесь можно усложнить задачу, если в конце будет возвращено логическое значение.

Наш новый результат должен выглядеть так:

Теперь, когда мы искали термин 2pac, мы ожидаем, что по крайней мере часть возвращенного музыкального видео, вероятно, будет принадлежать исполнителю «2Pac», но не обязательно все из них. В некоторых из них может быть только он.

Итак, давайте проделаем то же самое, что и каждый тест, но вместо этого сделаем некоторые.

let results = response.select('results');
// ... other tests using results in here ....
results
    .label('Check that at least some of the tracks are by 2Pac')   
    .some(function (result) {
        return result.property('artistName').toString() == '2Pac';
    });

Мы выбирали элемент результатов снова и снова, а это не самый эффективный способ. Обратите внимание, что мы изменили его, чтобы сохранить в переменной результатов, и теперь мы можем запускать любые тесты с этой ссылкой, вместо того, чтобы выбирать ее снова.

Утверждение some будет проходить, пока ЛЮБАЯ из итераций вернет true. Фактически, если вы предпочитаете его, вы можете использовать вместо него метод псевдонима any.

Теперь давайте рассмотрим первый результат в этом массиве. Мы ожидаем, что это будет 2pac (поскольку он наиболее соответствовал нашему поисковому запросу). Так что давай проверим это ...

results.first().property('artistName').equals('2pac');

Итак, здесь мы использовали наш элемент результатов, который мы ранее сохранили как переменную. Мы получили первый элемент из этого массива. И проверил, что он равен 2pac, теперь давайте запустим и посмотрим, что будет.

О нет! Это не удалось нам! Но почему?!?

Что ж, если мы рассмотрим сообщение об ошибке, оно содержит ключ, если вы присмотритесь. Метод equals для строк чувствителен к регистру. Ставим 2pac вместо 2 P ac. Конечно, мы могли бы изменить нашу тестовую строку на заглавную P, но, возможно, мы хотим, чтобы она была немного менее чувствительной.

В качестве альтернативы введите метод similarTo ().

results.first().property('artistName').similarTo('2pac');

Снова запустим наш тест:

Хороший! Мы вернулись к прохождению тестов, поскольку аналогично регистр не учитывается.

Мы также могли бы сделать что-то вроде этого:

results.first().find('artistName').toLowerCase().contains('pac');

Мы используем здесь найти вместо свойства. Они почти такие же, но не совсем. Find будет перемещаться вниз к дочерним элементам, где as property будет смотреть только на непосредственные атрибуты. Я люблю бросать в тебя новые вещи!

Итак, мы также видим toLowerCase (), который также устраняет нашу чувствительность к регистру, а затем мы видим новый метод contains (). Это ищет строку «pac» в любом месте этого значения.

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

results.first().attribute('artistId').is('number');

Как видите, я также использовал метод атрибута вместо свойства. Эти два псевдонима взаимозаменяемы. Используйте тот, который вам больше нравится семантически.

Наш окончательный тестовый результат:

Тада!

Надеюсь, вам понравилось это пошаговое руководство. Если да, я могу добавить еще один и представить дополнительные концепции, а также изменить его и показать вам, как тестировать свои HTML-страницы.