mad-fake-slack — это прежде всего, инструмент для тестирования вашего бота, без использования реальных серверов slack. В будущем это будет мощный инструмент для интеграционных и e2e тестов. Как видно, по гифке ниже, при тестировании, что-то может пойти не так :). И чтобы избежать этого, нужно тестировать не на продакшн, а локально, без привязки к реальным сервисам.
В большинстве случаев, интеграционные тесты, за неимением аналогов для реальных сервисов, проводят с использованием “реальных сервисов”.
Для успешного проведения таких тестов, нужен интернет, а если вдруг интернет исчезнет, то вы не сможете выпустить продукт. Кроме того, реальные сервисы, не позволяют сократить сценарии интеграционного тестирования.
К примеру, чтобы пред-заполнить данные, необходимо произвести множество отправок сообщений, файлов и так далее, прежде чем начать сценарий тестирования (если ваше приложение использует текущие данные в канале).
Фейковые сервисы (как правильно называть, можно почитать тут), позволяют сократить время тестирования и добавить возможность моделирования конкретной ситуации, без множества предшествующих ей, манипуляций. Если необходимо, чтобы клиент был как бы уже “залогиненным” в слаке, (вы же не будете тестить логин клиента в слак), то фейковый сервис позволяет убрать ненужные действия, ведь вам, нужно тестить бота или приложение, что предоставляет услуги. В этом деле, уже сейчас, может помочь mad-fake-slack. Пока он умеет мало, но уже с этим функционалом можно тестировать простейшие отправки/получения сообщений.
Недостатки фейковых сервисов и любой клиентской библиотеки
В этом мире, многое меняется и летит с огромной скоростью, а уж библиотеки и мессенджеры — часто обновляются разработчиками. Любая копия реального сервиса, будет отставать от реальной реализации.
И тут все зависит конечно, от команды поддерживающей фейковый сервис.
Но если в компании разрабатывающей сервис, приветствуется принцип обратной совместимости, то в принципе, все должно быть нормально.
Ведь даже библиотеки клиентов для слака, не могут 100% гарантировать, что они не отстанут, от разработчиков реального api слака. Так что, за это можно быть спокойным. Перед выпуском в продакшн, все равно нужно будет удостовериться на стейджинге в работоспособности всех функций. Так как тесты не всегда гарантируют правильность функционала, покрытого ими. Что-то может ускользнуть от взгляда разработчика.
Из чего состоит mad-fake-slack
- UI интерфейс очень напоминающий Слак клиент
- Возможность пред-заполнения данными канал или директ обычного пользователя (через редактирование файлов в папке db) или пользователя приложения, так как все данные хранятся на диске в формате json. Их легко заполнить и изменить.
- Есть один пользователь, который считается залогиненным (он указывается первым в коллекции пользователей)
- По умолчанию есть два канала general и random
- Присутствует пользователь приложения valera (он помечается спец маркой APP), которого также при желании можно изменить.
Дисковое хранилище данных mad-fake-slack
users.json — это файл, в котором хранятся данные об обычных пользователях, ботах и пользователях приложений.
teams.json — тут хранятся данные о командах, в которых может находиться пользователь.
sessions.json — тут хранятся ассоциации md5 хеша токена пользователя и его идентификатора. Для чего это нужно? Так как я не нашел никаких заголовков при соединении бота к ws серверу mad-fake-slack, то стало очевидным, как-то нужно понимать, какой пользователь — бот сейчас привязан к данному сокету. В итоге, родилось такое вот простое решение (приближенно аналогичное реальному решению в слаке). Так как при запросе на метод /api/rtm.connect или /api/rtm.start выдается информация с url для ws сервера (по которому бот и коннектится), можно подсунуть в параметры хеш, идентифицирующий пользователя. Но это, пока что зачатки секьюрити, которую в будущем можно будет также тестировать.
channels.json — тут находятся данные по каналам, которые так же можно легко менять. Этот список возвращается при запросе каналов из /api/channels.list
messages — это папка, в которой хранятся все сообщения. Для упрощения и разделения доступа к сообщениям (выбрана структура “файл на канал”). В качестве идентификатора файла, используется id канала. Таким образом в каждом из CXXXXXXXX.json файлах, хранятся сообщения каналов, в отдельности. Внутри каждого такого файла находится объект, первое свойство которого, хранит мета-информацию и пока там только поле хранящее кол-во записей с неочевидным названием “last_id” (в будущем исправлю этот недостаток). Далее следуют записи типа ключ: объект. Где объект — это запись сообщения с необходимым минимумом полей, а ключ — это значение поля ts — что гарантированно является уникальным ключом с содержанием даты в unix формате + инкрементальное значение.
Есть так же менеджер, импровизированной БД на диске, что позволяет объединить данные из нескольких файлов, по их ключам и выдать клиенту.
Примеры ответов на api запросы
В папке responses находятся примеры положительных ответов на запросы api с названиями методов api, для которых они предназначаются. Сейчас эти файлы используются как болванки ответов, в которых изменяются нужные поля, перед тем как отправить запросившему. Все примеры ответов были взяты с сайта документации апи слака https://api.slack.com/
Про UI
Пользовательский UI основан на Handlebars.js — для рендера на клиенте и express-handlebars — для серверного рендеринга. Это гибридный рендеринг, так как большая часть рендера страниц осуществляется на серверной части. На клиенте, используется реал-тайм прием сообщений через ws соединение. Серверные хелперы и темплейты, переиспользуются на клиенте, очень удобно.
Интерфейс очень похож на слак-клиент, чтобы было максимально привычно и удобно понимать механику и как отправлять сообщения и так далее. Не все конечно, удалось добавить в интерфейс, на первых порах и многое еще не работает, но тестировать через этот интерфейс простое общение с ботом, вполне можно.
Что сейчас доступно через интерфейс?
- Отправка сообщений в канал, в директ пользователю, в директ пользователю приложения (то есть боту).
- Получение сообщений в реалтайм в текущий активный канал.
Что предстоит сделать?
- Индикацию сообщений (красный кружочек для неактивного канала)
- Парсинг markdown сообщений
- Отображение более сложных по структуре сообщений
- Тестирование отправки файлов
- Кнопки на сообщениях (для реакций)
- Отображение состояния typing под текстовым полем
- Возможность добавить канал из UI
- Возможность добавить нового пользователя
- Возможность смены статуса текущего пользователя
- Возможность просмотра RAW сообщения в JSON в канале, чтобы увидеть его структуру “как есть”.
- Возможность создания треда сообщений
- Отображение тредов сообщений.
- Добавление отправки эмодзи
- Удаление пользователя
- Удаление приложения
- Удаление канала
- Архивирование канала
- Поддержка слеш-команд
И так далее, в общем цель основная, расширение возможностей для тестирования. Ведь при любом действии в UI, генерируются события и происходят вызова и отправка разных ивентов, данных. Можно будет соответственно проверять как реагирует на эти события ваш бот, создавать разные ситуации, которые в реальном слаке, было бы сложнее сделать.
Про серверную часть
Она построена на основе express.js и express-ws и позволяет обрабатывать следующие апи вызовы:
- /api/rtm.connect
- /api/rtm.start — сейчас пока этот метод выдает ровно столько же информации, сколько и rtm.connect. В будущем ответ будет приведен в соответствие с ожидаемым по документации в api.
- /api/auth.test
- /api/channels.list
- /api/chat.postMessage
Так же присутствует серверный рендер следующих страниц:
/ — главная страница, по умолчанию текущий канал general и соответственно его контент и отображается на странице.
/messages/:id — при клике по названию канала, уходит запрос на сервер, где парсится идентификатор канала и если он есть, в ответ будет возвращена вся страница с отображенным контентом канала. Это касается и директа и открытого канала и пользователя приложения.
/api/chat.postMessage — если отключить JS то форма отправки данных все равно будет работать, так как в этом случае будет отправлен POST запрос на сервер в формате обычной HTTP формы и в ответ будет отображена страница канала, с новым сообщением внутри.
Про тестовое api
Сейчас доступен метод, позволяющий очистить базу данных в фейкового слака в памяти.
GET /test/api/db/reset — при отправке запроса на этот URL данные в базе данных в памяти, заново читаются из папки db и таким образом возвращаются в первоначальное состояние. Теперь, необходимо только обновить страницу файкового слака в вашем браузере (если она была открыта до этого).
В будущем кол-во методов помогающих в интеграционном тестировании будет расти по мере необходимости.
По поводу секьюрити
Пока нет проверки токена на соответствие тому, что указывает бот при обращении к апи или веб-сокет серверу. Проверка будет обязательно добавлена в будущем с соответствующими серверными ответами, чтобы можно было и неудачную авторизацию тестировать.
Пример реального использования
В папке examples, находится пример rtm бота, что не использует веб хуки, а вместо этого использует ws соединение. Сначала нужно стартовать mad-fake-slack командой npm start. Затем, запустить бота выполнив команду npm run example:rtmbot
Бот в примерах, очень прост, он получает любое сообщение в канале и сразу же отправляет в тот же канал, с припиской о том, что вы отослали вот такое вот сообщение.
Так же, можно наблюдать следующую активность в консоле VSCode (так как она используется для локальной разработки + Remote-Containers расширение).
Что необычного в реализациях апи слака, на разных языках
Вот к примеру официальный апи на node.js https://github.com/slackapi/node-slack-sdk, использует внутри стейт-машину и каждый запрос отправляемый на сервер содержит поле id, что увеличивается с шагом в 1. И при этом требуется отсылать в ответе поле reply_to с тем id что был отправлен на сервер.
При этом в библиотеке на python вообще нет привязки к такого рода эхо.
Хотелось бы, чтобы как-то стандартизировали эти моменты, ведь в документации поле reply_to упоминается в несколько другом акценте.
If you’re reconnecting after a network problem this initial set of events may include a response to the last message sent on a previous connection (with a reply_to) so a client can confirm that message was received.
Собственно необходимость в reply_to, появляется только в случае, если был разрыв соединения. Но для node.js версии, даже простые ping/pong запросы должны сопровождаться этим полем. Хотя может быть так, что я что-то упустил, но проблем с питон версией не было.
Где можно опробовать в действии mad-fake-slack?
Вот тут https://github.com/maddevsio/mad-fake-slack
Пример интеграционных тестов на jest-puppeeter
В проекте присутствуют примеры интеграционных тестов для бота в папке examples. Которые проверяют его состоятельность и адекватность. Примеры всех тестов можно посмотреть тут. Эти тесты запускаются командой
npm run example:rtmbot:integration
Вот несколько примеров тестов:
Следующий пример, более длинный, для проверки реакции бота, если сообщения отправляются в разные каналы, в данном случае в random и general.
Заключение
Впереди, еще много работы и это лишь первый анонс средства тестирования. Надеюсь этот инструмент сможет выявлять проблемы и помогать в тестировании в будущем. Спасибо большое за прочтение данной статьи!
Ранее статья была опубликована тут.