И снова здравствуйте! Меня зовут Ярослав, и я лидер направления автоматизации тестирования в Центре развития финансовых технологий Россельхозбанка. В этой статье я поделюсь своим опытом создания Telegram Bot-а для автоматизации тестирования.

Как появилась идея создать Telegram Bot для автотестов?

Мы хотели облегчить пользователям громоздкую цепочку действий из 4 шагов:

1) подключение к сети;

2) вход в VDI;

3) вход в Jenkins;

4) запуск автотестов или проверка окончания сборки.

Тогда нам пришла в голову мысль, что Telegram Bot может решить эту задачу.

Забегая вперед, скажу, что это «зашло». Реакция пользователей после запуска бота была позитивной: «Удобно!», «Круто!», «А что, так можно было?».

Определяем функции бота.

Дано:

1)    Собственный Jenkins (его поддерживает команда автоматизации);

2)    Настроенные проекты, подключенные к автоматизации по одному шаблону и соответственно работающие одинаково;

3)    Язык программирования — Java.

В этой статье я подробнее рассказываю о внутренних процессах проекта.

Задача:

1)    Запустить автотесты из Telegram;

2)    Понять состояния сборки из бота.

Исходя из этих критериев, мы можем выделить команды, которые будут в главном меню бота:

1)    Запуск автотестов;

2)    Получение очереди сборок;

3)    Подписка на уведомления.

Начинаем создавать Telegram Bot.

1.  Создаем бота через BotFather:

В свободном доступе находится много инструкций по созданию бота в Telegram, однако стоит обратить внимание на несколько моментов:  

1)    Начните со ссылки на BotFather;

2)    Сохраните «имя бота»;

3)     Сохраните Token «token to access the HTTP API».

Последние два параметра нам пригодятся в дальнейшем.

2.  Тестируем отправку сообщений

a) Нужно отправить боту сообщение. Для этого в браузере вставляем следующий URL:

https://api.telegram.org/bot5555555555:AAA-CCmmQQwKK1s5dGGttt7AAAAAAAAAA7oo/getUpdates

"5555555555:AAA-CCmmQQwKK1s5dGGttt7AAAAAAAAAA7oo" — это ваш token бота, который я просил вас сохранить (пункт 1.3).

Получаем ответ следующего формата:

{
  "update_id": 213155906,
  "message": {
    "message_id": 3312,
    "from": {
      "id": 630654728,
      "is_bot": false,
      "first_name": "NAMENAME",
      "username": "myUserName",
      "language_code": "ru"
    },
    "chat": {
      "id": 777777777,
      "first_name": "NAMENAME",
      "username": "myUserName",
      "type": "private"
    },
    "date": 1063328708,
    "text": "Privet Andrei"
  }
}

В блоке «chat» будет "id":777777777. Копируем его.

b) В браузере вставляем следующий URL:

https://api.telegram.org/bot5555555555:AAA-CCmmQQwKK1s5dGGttt7AAAAAAAAAA7oo/sendMessage?text=Privet Andrei&chat_id=777777777

где «5555555555:AAA-CCmmQQwKK1s5dGGttt7AAAAAAAAAA7oo» — это ваш token бота (пункт 1.3), а «777777777» — это ваш chat «id» (пункта 2.a.)

Получаем ответ следующего формата:

{
  "ok": true,
  "result": {
    "message_id": 3610,
    "from": {
      "id": 5511726085,
      "is_bot": true,
      "first_name": "NAME",
      "username": "Name_bot"
    },
    "chat": {
      "id": 610044722,
      "first_name": "NAMENAME",
      "username": "myUseName",
      "type": "private"
    },
    "date": 1065329540,
    "text": "Privet Andrei"
  }
}

В чате у вас появится сообщение от бота "Privet Andrei".

3.  Подготовим Jenkins.

3.1  Создаем и настраиваем пользователя для запуска автотестов

3.1.1  Создаем пользователя

Путь в Jenkins: Настроить Jenkins – База данных пользователей Jenkins.

Или URL – «http://JenkinsHost:JenkinsPort/manage/securityRealm/»

3.1.2  Раздаем права на запуск job в Jenkins созданному пользователю.

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

3.1.3  Создаем Api Token

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

В настройках ищем пункт «Api Token».

Создаем его и сохраняем. Он пригодится для запуска Job.

Далее будем называть его TOKEN_NAME.

3.1.4  Тестируем запуск Job-ы

Jenkins предлагает следующую схему:

Use the following URL to trigger build remotely:

JENKINS_URL/job/ProjectName /job/FOLDER/job/JobName/build?token=TOKEN_NAME or /buildWithParameters?token=TOKEN_NAME

Эту подсказку можно найти в редакторе Job-ы в пункте «Trigger builds remotely (e.g., from scripts)».

У нас в проектах есть 2 параметра: BRANCH (Ветка) и TAG (Тег для запуска).

Следовательно, URL для запуска будет выглядеть следующим образом:

JENKINS_URL/job/ProjectName/job/FOLDER/job/JobName/buildWithParameters?token=TOKEN_NAME&TAG=@all&BRANCH=test

Вставляем URL в браузер, запускаем и проверяем, что в Jenkins стартовала сборка Job-ы.

4.  Разворачиваем базу данных.

Вы можете использовать любую подходящую для вас базу данных, в нашем случае это H2. База данных нам понадобится для хранения состояния пользователя и некоторых его данных, например, «chat_id» Telegram. Найти инструкцию по установке можно на просторах интернета, однако вам пригодиться ссылка для скачивания: «https://h2database.com/html/main.html».

5.  Делаем каркас основных подкапотных функций бота.

Для реализации функций бота на java мы использовали

<dependency>
    <groupId>org.telegram</groupId>
    <artifactId>telegrambots</artifactId>
    <version>lastVersion</version>
</dependency>

Необходимые функции бота:

a.    читать сообщения;

b.    отправлять сообщения;

c.    создавать, изменять, читать данные пользователя в БД;

d.    создавать, изменять, читать состояние пользователя в БД (где он находится и какую кнопку выбрал);

6.  Реализуем функцию «Запустить автотесты»

Чтобы запустить тесты, нужны следующие данные:

a.    название проекта;

b.    стенд;

c.    ветка;

d.    тег;

e.    TOKEN_NAME из пункта 3.1.3

Из собранных данных можно составить URL для запуска

JENKINS_URL/job/Название проекта/job/FOLDER/job/Стенд/buildWithParameters?token=TOKEN_NAME&TAG=Тег&BRANCH=Ветка

Схема для понимания, почему URL выглядит таким образом:

С помощью сохранения состояний в БД и кнопок меню в Telegram получаем эти данные и «запускаем» собранный URL.

7.  Реализуем функцию «Получить очередь сборок»

Эта функция должна возвращать:

a.    список проектов, стоящих в очереди;

b.    список проектов, которые сейчас собираются;

Чтобы увидеть оба пункта, нам пригодится api Jenkins-а.

Для получения очереди достаточно обратиться по URL

http://JenkinsHost/queue/api/json

либо

http://JenkinsHost/queue/api/xml

в зависимости от того, с каким форматом вам удобнее работать.

Для получения проектов, которые собираются, используйте URL:

http://JenkinsHost/computer/api/json?tree=computer[executors[currentExecutable[url]],oneOffExecutors[currentExecutable[url,actions]]]

Вернутся сборщики и проекты, которые собираются.

Формат возвращаемого сообщения:

Место в очереди - N
Job Name - ProjectName/job/Folder/job/Stand/"
TAG - @all
BRANCH - test
Build Status - В очереди или Собирается

8.  Реализуем функцию «Подписка на уведомления»

Для реализации функции отправки уведомлений есть несколько путей:

1)    Сложный. Нужно собрать все «chat_id» переписки пользователей с ботом и по всему списку «chat_id» по триггеру рассылать сообщения по очереди;

2)    Легкий. Создать отдельный канал в Telegram для публикации своих уведомлений и сделать Bot-а администратором. Таким образом все, кто подписан на канал, получат уведомления. По сути у вас будет один «chat_id», на который вам нужно будет отправлять уведомления.

Мы выбрали второй вариант. Во-первых, так быстрее. Во-вторых, чат пользователя с ботом не забивается уведомлениями из Jenkins. Автотесты собираются достаточно часто.

Способ отправки сообщения такой же, как и в пункте 2.b, меняется только «chat_id».

Куда и как отправлять уведомления мы определили — теперь нужно реализовать эту функцию. Мы хотим понимать, когда Job-а начала сборку и когда закончила её. Формат уведомления:

Job_Name - ProjectName/job/Folder/job/Stand/"
Build_Number – N
TAG - @all
BRANCH - test
Build_Status – Start/Finish
Allure_URL – JenkinsHost/ProjectName/job/Folder/job/Stand/BuildNumber/allure/

где «Allure_URL» возвращаем только в конце сборки.

Чтобы отправить сообщения, мы использовали 2 плагина для Jenkins:

a.    Execute Groovy script — используем для отправки сообщения о старте сборки.

b.    Groovy Postbuild — используем для отправки сообщения об окончании сборки.

Результат

1)    Автотесты можно запускать из любой точки, где есть Telegram и интернет.

2)    Процесс запуска автотестов ускорился с 1 минуты до 10 секунд.

3)    Теперь не нужно постоянно заходить в Jenkins, чтобы проверить состояние сборки проекта. Уведомление об окончании сборки придет в Telegram сразу с ссылкой на отчет.

4)    Можно посмотреть очередь сборки проектов.

Комментарии (5)


  1. alcochtivo
    10.11.2022 13:09
    +2

    Круть, писал такого же, но на Go, лет пять назад... дальше личного пользования не ушло, и видимо зря) А теперь вот побаловался и сделал тупенького бота, для проверки ответа сервера. Можно добавить урл, который будет дёргаться раз в минуту, и если код ответа не 200, и\или тело ответа равно нулю - бот будет алярмить в личку.


    1. yaroslav796 Автор
      10.11.2022 19:34
      +2

      Спасибо! Хорошая идея!


  1. Doman
    10.11.2022 17:10
    +2

    Не до конца понял - зачем запускать тесты вручную? Если в продукте ничего не изменилось, то тесты запускать незачем. Если в продукте что-то изменилось, то запускать надо до/после изменений автоматически.

    Получение упавшего тест-репорта полезно, да.


    1. yaroslav796 Автор
      10.11.2022 19:42
      +1

      Проект состоит из 11 продуктов, которые собираются отдельно друг от друга. Т.к проект нужно тестировать в целом, то автозапуск при сборке каждого из 11 продуктов будет лишним. + есть ограничения в виде тестовых данных. Здесь они создаются в других системах и часто чистятся. Что тоже накладывает ограничения в виде их подготовки. А так да, есть продукты, которые не зависят от внешних факторов. Там реализован автозапуск из pipeline деплоя на стенд. И там уже только уведомления полезны.


  1. insomnia77
    11.11.2022 20:02

    На мой взгляд, зря потраченное время на разработку велосипеда.
    Согласен с предыдущим комментарием, что запускать тесты вручную не нужно. Можно запускать тесты после деплоя изменений на стенд или, например, по расписанию полный регрессионный набор. Если у вас есть зависимости от тестовых данных и 11 продуктов, то добавьте эти зависимости в pipeline и сэкономите кучу времени избавившись от ручных запусков.
    В рамках исключения, всегда можно просто зайти в мобильную версию CI/CD и запустить job.

    Насчет нотификаций в корпоративный чат - это уже давно реализовано в CI/CD системах и не нужно пилить велосипеды. Например, в Circle CI делается одной строчкой
    orbs:
    ms-teams-notifier: oktapodia/ms-teams-notifier@1.0.0
    Уверен, что Jenkins тоже есть плагины.