Управление автоматизированными тестами с помощью Telegram

Работая QA инженером, я разрабатывал систему автотестестирования. Столкнулся с рядом проблем:

  • На каждый вид тестирования приходилось создавать свои job в CI и запускать их руками.
  • Разработчики отказывались запускать кейсы автотестов самостоятельно.
  • Отсутствие возможности запуска автотестов из любой точки \ устройства.
  • QA инженеры ручного тестирования не могли самостоятельно проводить запуск автотестов.

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

Описание идеи:

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

Инструменты:

Инструменты
  • Язык программирования — Python
  • Тестовый фреймворк — Pytest
  • HTTP клиент — Requests
  • DataBase — SQLite3
  • ORM — Peewee
  • CI система — Travis CI



Содержание

  1. Подготовка
  2. Регистрация бота
  3. Подготовка репозитория с тестами
  4. Тесты и логирование
  5. Формирование отчета
  6. Настройка Travis CI
  7. Настройка бота
  8. Принципы работы бота
  9. Деплой на Heroku


Регистрация бота


Первым делом, нам надо зарегистрировать телеграм бота и получить его уникальный id, который является токеном. Для этого необходимо написать сообщение /start боту @BotFather.
Наша основная команда это /newbot, введя которую, нас попросят придумать имя бота.
Но есть одно правило — имя должно заканчиваться на bot. BotFather принимает имя бота и возвращает ваш токен. Активируйте бота, начав переписку в чате. Далее нужно отправить запрос к API на метод getUpdates.

https://api.telegram.org/bot{ВАШ_ТОКЕН}/getUpdates

Запомните полученный сhat_id.


Подготовка репозитория с тестами


Далее необходимо организовать репозиторий с тестами, либо использовать заранее подготовленный для статьи.


Тесты и логирование

Создадим тестовые функции и отметим их pytest mark — full, smoke и bird.

Важно добавить логирование в наши тесты, создав файл pytest.ini и дописав вызовы метода info из библиотеки logging в тестовых функциях.
Файл pytest.ini содержит в себе шаблоны для live logs и файла логирования.

Пример тестов
import pytest
import requests
import logging


@pytest.mark.full
@pytest.mark.smoke
def test_cat_facts():
    query = {"animal_type": "cat", "amount": "2"}
    response = requests.get("https://cat-fact.herokuapp.com/facts/random", params=query)
    logging.info(f"Request url: {response.request.url}, body: {response.request.body}")
    logging.info(f"Request status: {response.status_code}, body: {response.text}")
    assert response.status_code == 200

@pytest.mark.full
@pytest.mark.smoke
def test_dog_facts():
    query = {"animal_type": "dog", "amount": "2"}
    response = requests.get("https://cat-fact.herokuapp.com/facts/random", params=query)
    logging.info(f"Request url: {response.request.url}, body: {response.request.body}")
    logging.info(f"Request status: {response.status_code}, body: {response.text}")
    assert response.status_code == 200


@pytest.mark.full
def test_horse_facts():
    query = {"animal_type": "horse", "amount": "2"}
    response = requests.get("https://cat-fact.herokuapp.com/facts/random", params=query)
    logging.info(f"Request url: {response.request.url}, body: {response.request.body}")
    logging.info(f"Request status: {response.status_code}, body: {response.text}")
    assert response.status_code == 200

@pytest.mark.bird
def test_bird_facts():
    query = {"animal_type": "bird", "amount": "2"}
    response = requests.get("https://cat-fact.herokuapp.com/facts/random", params=query)
    logging.info(f"Request url: {response.request.url}, body: {response.request.body}")
    logging.info(f"Request status: {response.status_code}, body: {response.text}")
    assert response.status_code == 200



pytest.ini
[pytest]

markers =
    smoke: for smoking testing
    full: for regression testing
    bird: facts only bird

log_cli = 1
log_cli_level=INFO
log_cli_format = %(asctime)s [%(levelname)8s] %(message)s
log_cli_date_format='%Y-%m-%d %H:%M:%S'

log_file = test_log.log
log_file_level=INFO
log_file_format= %(asctime)s [%(levelname)8s] %(message)s
log_file_date_format='%Y-%m-%d %H:%M:%S'




Формирование отчета

Создаем скрипт, который после окончания сборки собирает информацию из CI системы и присылать их в телеграм чат, совместно с логами.
Внутри скрипта надо заменить значения TELEGRAM_BOT и CHAT_ID, на полученные вами ранее.

Код скрипта
import requests
import os

TRAVIS_TEST_RESULT = os.environ.get("TRAVIS_TEST_RESULT")
TRAVIS_REPO_SLUG = os.environ.get("TRAVIS_REPO_SLUG")
TRAVIS_BRANCH = os.environ.get("TRAVIS_BRANCH")
TRAVIS_JOB_WEB_URL = os.environ.get("TRAVIS_JOB_WEB_URL")
TRAVIS_COMMIT_MESSAGE = os.environ.get("TRAVIS_COMMIT_MESSAGE")
TELEGRAM_TOKEN = "808619876:GHrtj9zs-KvKhhtWyu1YoxjtIikUYMGVjD8g"
CHAT_ID = "272560060"

if TRAVIS_TEST_RESULT != 0:
    build_status = "Успешно"
else:
    build_status = "Неуспешно"

TEXT = f"Прогон завершился: {build_status} \n Репозиторий: {TRAVIS_REPO_SLUG} \n Ветка: {TRAVIS_BRANCH} \n Commit сообщение: {TRAVIS_COMMIT_MESSAGE} \n Веб-лог: {TRAVIS_JOB_WEB_URL}"


def send_message():
    URL = f"https://api.telegram.org/bot{TELEGRAM_TOKEN}/sendMessage"
    body = {'chat_id': CHAT_ID, 'text': TEXT}
    response = requests.post(url=URL, json=body)
    return response


def send_file():
    URL = f"https://api.telegram.org/bot{TELEGRAM_TOKEN}/sendDocument"
    body = {'chat_id': CHAT_ID}
    file = {"document": open("test_log.log")}
    response = requests.post(url=URL, data=body, files=file)
    return response


send_message()
send_file()


Скрипт использует системные переменные и получает значения от Travis CI.

Если значение TRAVIS_TEST_RESULT не равно нулю — подставляется значение “Успешно”, сначала отрабатывается функция send_message, которая отправляет в чат информацию о сборке (название репозитория, выбранная ветка, название используемого коммита, ссылка на веб-лог), далее отрабатывается функция send_file, которая отправляет файл с логами.

В репозиторий с тестами добавляем конфигурационный файл — travis.yml. Внутри описываем pipeline по которому будет работать сборка.

travis.yml
language: python
python:
  - "3.7"
install:
  - pip install -r requirements.txt

script:
  pytest -m smoke

after_script:
  - python tg_command.py


Далее нам надо задеплоить репозиторий на GitHub, чтобы добавить его в Travis CI.


Настройка TRAVIS_CI


Заходим на сайт.
Авторизируемся с помощью аккаунта GitHub. Переключаемся на вкладку Dashboard. Предварительно открыв DevTools (Network), в подвкладке Repositories на сайте напротив репозитория с тестами передвигаем ползунок — активируем его сборку. Во вкладке Network (DevTools) приходит запрос active, в preview которого есть информация об id репозитория, номер необходимо запомнить (скопировать / записать). Переключаемся на сайте в подвкладку Setting. Копируем или запоминаем токен — он нам понадобиться.


Настройка бота


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

Внутри репозитория находятся файлы:

  1. main.py — скрипт бота;
  2. models.py — файл с модельками для ORM;
  3. conf.ini — файл с конфигурационными переменными;
  4. runtime.txt — фиксированное значения версии Python для Travis CI;
  5. procfile — настройка для gunicorn;
  6. wsgi.py — файл запуска приложения c gunicorn.

Чтобы ваш бот заработал, надо заменить данные в conf.ini, а именно:

  • travis_token — указать полученный токен к Travis CI;
  • travis_base_url — указать адрес Travis CI API;
  • travis_repository_id — указать id репозитория с автотестами, внутри Travis CI;
  • telegram_chat_id — указать id чата телеграмма, куда будут отправлять сообщения от бота;
  • telegram_bot_url — указать url до бота.

Пример conf.ini

[travis]
travis_token  = token HkjhkjgGKJhjgFGfdgd
travis_base_url = https://api.travis-ci.org
travis_repository_id = 10898384
[telegram]
telegram_chat_id = 24234234
telegram_bot_url = https://api.telegram.org/bot87543366:AAHtj9zs-Kv4zGWyu1eTXegikUYMGVjD8g/



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

Важно, что каждый запрос должен отдавать статус ответа равный 200. В противном случае телеграмм начинает циклично отправлять запросы, пока не получит валидный ответ.

Бот имеет набор команд:

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

  • add_m — добавление комплекта тестирования (python marks).
    Шаблон: *команда* {описание комплекта} {разделитель} {название mark}.
    Пример: add_m Тестирование птиц / bird.
  • add_b — добавление ветки для тестирования.
    Шаблон: *команда* {описание ветки} {разделитель} {название ветки из git}.
    Пример: add_b Мастер / master.
  • select — позволяет выбрать ветку для тестирования по умолчанию.
    Шаблон: *команда*.
    Пример: После ввода команды select, появляются кнопки выбора веток, который были занесены в базу командой add_b.
  • run — Команда запуска сборки.
    Шаблон: *команда*.
    Пример: После ввода команды run, появляются кнопки выбора комплектов автотестов, которые были занесены в базу командой add_m. При запуске автоматически выбирается ветка, указанная командой select.
  • del_m — удаляет комплект тестов.
    Шаблон: *команда* {название marks}.
    Пример: del_m bird.
  • del_b — удаляет занесенный в БД ветки.
    Шаблон: *команда* {ветка из git}.
    Пример: del_b master.

Как работает бот?

1. Пользователь добавляет комплект тестов (add_m):
Команда разделяет данные от пользователя на 2 части — описание и название ветки в git. Название записывается в колонку mark_name внутри БД, а описание в колонку mark_description.

2. Пользователь добавляет ветки (add_b):
Команда разделяет данные от пользователя на 2 части — описание и название ветки в git. Название записывается в колонку branch_name внутри БД, а описание в колонку branch_description.

3. Пользователь выбирает ветку по умолчанию (select):
Пользователь получает в чат кнопки, сформированным по данным из таблиц branch_description и branch_name. Пользователь выбирает кнопку с необходимой веткой. Она записывается в таблицу favorite_branch.

4. Пользователь запускает инициализацию билда (run):
Пользователь получает в чат кнопки, сформированным по данным из таблиц
mark_description и mark_name. Пользователь выбирает кнопку с комплектом для запуска автотестов.

На основе выбранных пользователем данных, бот формирует запрос в методе trigger в классе TravisCI и отправляет его на Travis для исполнения. Внутри системы Travis активируется опция trigger a build. Эта опция переопределяет travis.yml файл, изменяя секцию script на выбранные пользователем данные.


Деплой на HEROKU


Чтобы бот заработал, его необходимо задеплоить на хостинг. Я рекомендую использовать Heroku, потому что эта платформа имеет бесплатный тариф, которая предоставляет необходимые мощности для работы бота.

Как развернуть бота?

Чтобы не описывать весь процесс, оставлю ссылку на официальную документацию для старта:

Если вы хотите работать с Heroku через GUI, залейте код на Github. Вам надо зарегистрироваться через web-интерфейс Heroku. После регистрации, нажать New -> Create new app -> Введите название app и выбрать регион. Перейдите на вкладку Deploy и выберете в Deployment method интеграцию с Github.

Перед нами появляется блок для поиска репозитория. Вводим название репозитория и нажимаем кнопку Search. В выдаче поиска, напротив названия репозитория нажимаем кнопку Connect. В блоке Manual deploy выбираем ветку и нажать “Deploy”.

Последний момент — необходимо активировать вебхуки с помощью GET-запроса:
https://api.telegram.org/bot{id_бота}/setWebhook?url=https://{имя_приложения}.herokuapp.com/bot


Ботом можно пользоваться. Проверяем, что у нас все получилось:

image
  • +10
  • 5,3k
  • 3
Поделиться публикацией

Похожие публикации

AdBlock похитил этот баннер, но баннеры не зубы — отрастут

Подробнее
Реклама

Комментарии 3

    0
    На каждый вид тестирования приходилось создавать свои job в CI и запускать их руками.

    Не знаю как там в travis, в teamcity делается нажатием одной кнопочки (опционально, ввести параметры типа бранча/билда, который надо протестировать)


    Разработчики отказывались запускать кейсы автотестов самостоятельно.

    Автоматический запуск на коммит/билд решит проблему. Разработчик только получит email, если тесты упали


    Отсутствие возможности запуска автотестов из любой точки \ устройства.

    Это действительно на столько важно? Я лично не могу представить ситуацию, когда вне работы (== нет рабочего устройства под рукой) потребовалось бы запускать тесты


    QA инженеры ручного тестирования не могли самостоятельно проводить запуск автотестов.

    Настраиваете доступ к CI и вуаля

      0
      Спасибо за комментарий!

      Я попытаюсь прояснить ситуацию.

      Автоматический запуск на коммит/билд не решит проблему, потому на каждую фичу могут понадобиться различные комплекты тестов. Пример: Разработчик изменил регистрацию, значит нужно запустить тесты только на регистрацию. Для это разработчику нужно спросить какой комплект тестов для регистрации (каким marks) отмечено, залезть в CI, настроить билд под данные тесты и запустить. Как правило на моем практики ребята-разработчики ленились это делать, поэтому вариант набрать в чате run и тыкнуть кнопку — выглядит быстрее и проще (на сугубо мой взгляд)

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

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

    Самое читаемое