WSTester – JS библиотека для тестирования веб-сервисов с ВебСокетами

Добрый день, Хабрасообщество! Как и большинству айтишников, мне нравится создавать что-то новое, классное, нечто способное как-то повлиять на мир или хотя бы принести небольшую пользу другим людям. Надеюсь, что описываемый далее инструмент для тестирования онлайн систем с ВебСокетами как раз такая вещь.


logo


Предыстория

Большинство идей рождаются в результате активной и разнообразной работы, и данная идея не исключение. Для тестирования своей кросс-платформенной игры мне пришлось писать много тестов. Для iOS в среде Xcode предоставляется удобнейший встроенный функционал, (алгоритмы в Java под Android я просто переписывал с Obj-C, решил обойтись без юнит-тестов). На серваке многие алгоритмы можно тестировать изнутри при его локальном запуске, а для проверки правильной обработки HTTP запросов можно легко написать скрипт на Python с библиотекой requests.


Однако когда для взаимодействия клиентов-сервера пришлось добавить канал связи по WebSocket«ам, я не уделил его тестированию нужного внимания. В итоге, в игре не было возможности создать нового юзера через ВебСокеты, а приложение использовало именно их… Глядя на статистику я быстро заподозрил что-то неладное, но принял решительные действия лишь спустя месяц-другой.


Главной причиной появления этой ошибке в production«e было то, что для тестирования ВебСокетов не было видно простых путей — ведь в отличии от HTTP, где у каждого запроса есть ответ, в ВебСокетах можно отправить сколько угодно сообщений на сервер и не получить ответа вовсе; или же ничего не отправлять, зато получить любое количество различных сообщений.


Поискав в Интернете, я не нашёл каких-то рекомендаций по этой теме. Возможно я плохо искал, или возможно эта технология ещё слишком молодая, и для крупных проектов пишутся собственные системы для тестирования, а в малых всё делается вручную. Однако я увидел небольшую пустоту в мировом программном континууме и поспешил её закрыть.


В результате получились JavaScript библиотека WebSocket Testing Engine (вкратце WSTester) и веб-страница для работы с ней через готовый GUI, который принимает JS файл с кодом тестов. Все исходники доступны на ГитХабе.


Принцип работы

WSTester работает как конечный автомат — на вход подаются потоки выполнения, они исполняются независимо и последовательно, их можно считать за юнит-тесты. Каждый поток выполнения — это массив или словарь JavaScript, он состоит из юнитов, и в каждый момент времени существует лишь один текущий юнит.


Первым в потоке вызывается юнит с индексом 1, последующие могут быть любыми. Если поток это массив, то следующим считается юнит с индексом равным текущему + 1, но можно и поменять индекс следующего юнита. Если поток является словарём, то в нём всегда нужно самостоятельно указывать индекс следующего юнита.


Структура объекта юнита такова:


{
    name: string,
    enter: function () {},
    task: function (ws, ref) {},
    condition: function (data) {},
    key: string,
    val: any type,
    finalise: function (ws) {},
}


Поле name используется для вывода информации по юниту, enter и task применяются при переходе к новому текущему юниту, а condition, key, val и finalise при получении нового сообщения.


Успешно выполненным юнит считается тогда, когда полученное сообщение удовлетворит одному из условий:


  • Если указана функция condition, то юнит завершается успешно, если функция с аргументом полученным сообщением вернёт true или индекс следующего юнита.
  • Если указаны key и val, то юнит завершается успешно, если полученное сообщение имеет поле с названием равным key и значением этого поля равным значению val. Кстати, если val является массивом, то все его значения будут проверены по отдельности.
  • Если указан key, но не val, то юнит завершается успешно, если полученное сообщение имеет поле с названием равным key.


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


Описанной выше информации достаточно для написания тестов, которые можно запускать через готовый интерфейс WSTester. Значительно больше и подробней о принципах работы можно узнать тут и ещё здесь.


В интерфейсе можно менять разные настройки: адрес WebSockets сервера, время ожидания подходящего сообщения до провала юнита, нужно ли создавать новые подключения для каждого потока, время между юнитами. Эти же параметры можно задать в JS файле тестов для максимальной автоматизации. Также, GUI может принимать файлы тестов по указанному URL или напрямую с компьютера.


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


Примеры использования

Основной функционал разрабатывался в рамках проекта вышеупомянутой игры, как аналог тестам по HTTP запросам, однако впоследствии был проверен и расширен в работе с несколькими другими сервисами. Ниже указано несколько тестов, описание и ссылки на файлы и сервисы.


  • data_toy.js — модификация реальных тестов логической игры TacticToy. Содержит 4 потока, 16 юнитов. Запустить файл.
    Фичи: condition; поток как словарь; пропуск юнитов с использованием condition и ref.next.
  • data_gdax.js — образец теста для GDAX WebSocket API. Содержит 3 потока, 3 юнита. Запустить файл.
    Фичи: val как массив; args.split.
  • data_block.js — образец теста для Blockchain transaction WebSocket API. Содержит 1 поток и 3 юнита. Запустить файл.
    Фичи: finalise.
  • data_ether.js — образец теста для The Etherscan Block Explorer WebSocket API. Содержит 2 потока и 6 юнитов. Запустить файл.
    Фичи: поток как словарь; ref.next; args.split.


Стоит отметить, что хотя данные тесты и содержат весь функционал WS Testing Engine, они всё же не достигают каких-либо пределов, оставляя огромный простор для фантазии: можно определить и использовать внешние переменные, функции, объекты и работать с ними в юнитах, можно сделать циклические переходы между юнитами по навороченным правилам, и т.д. Язык JavaScript к таким вещам очень располагает.



P.S.


  • Конечно, упомянутую ошибку можно было выявить и другими способами, но суть рассказа не в этом.
  • Почему JavaScript? Потому что это достаточно мощный и в то же время легковесный кросс-платформенный язык, в котором ВебСокеты поддерживаются из коробки, и ещё к нему можно легко добавить интерфейс (HTML+CSS).
  • Я стараюсь быть точным в своих высказываниях и используемых терминах, но если кто-то заметит ошибки, прошу не ругать, но доброжелательно прокомментировать.
  • К сожалению, мне мало удалось найти открытых API на ВебСокетах, где не нужна предварительная регистрация. Если у Вас есть предложения для расширения списка — смело предлагайте свои варианты.


Код библиотеки и прочие файлы на ГитХабе.

© Habrahabr.ru