Всем привет! Меня зовут Стас, я ведущий инженер отдела сертификационного тестирования компании YADRO. Однажды мне стало лень вручную проставлять статусы тестов PASSED/FAILED в TestY TMS, и я написал свое клиент-серверное приложение ATS Studio. С его помощью я избавил от боли ручного управления несколько команд YADRO.

Как мне удалось это сделать, если я не пишу код на Python, и чему я научился в процессе, рассказываю в статье.

Боль: ручное управление TestY

Весной этого года моя команда решила полностью переехать в TestY — систему управления тестированием с открытым исходным кодом, которую разработали наши инженеры. По функционалу она близка к TestRail, но доступна в России и поддерживается разработчиками и комьюнити. В TestY можно заводить тест-кейсы, собирать их в тестовые планы, проставлять статусы и прикреплять отчеты.

Зачем нужно было переезжать? Очень хотелось собирать и хранить данные тестирований разных отделов и команд в одном месте и в одном стиле. Иначе, как водится у инженеров, каждый обзаведется пачкой тестов и будет хранить их у себя «под ковриком». А когда доходит дело до презентации результатов другим, оказывается, что «коврик» исчез или его нет под рукой.

Заезжать в TMS всегда больно. И ладно еще писать, оформлять тест-кейсы с нуля — это полбеды. Главная боль — ведение отчетности по прохождению тестов, которая сводится к такой цепочке:

  • запустил скрипт на SUT (System Under Test, тестовая машина),

  • дождался результата,

  • открыл TestY,

  • нашел нужный тест в тестовом плане,

  • выставил статус,

  • прикрепил лог,

  • повторил 20 раз.

А если тестов 200? А если их нужно прогонять каждый день? А если кто-то забыл прикрепить файл или поставил не тот статус?

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

На одной из прошлых работ мы буквально «причесывали» тест-планы по полдня. Я вспомнил об этом и понял: не хочу заниматься этим снова. Но как  это автоматизироват��? Процесс простейший: пусть что-то общается с TestY и само ставит нужные статусы, ведь результатов выполнения теста или скрипта не так много. Отсюда и родилась первая идея: нужен клиент для TestY. Пусть он сам загрузит тестовый план, выполнит тесты (они же скрипты), сам узнает, прошел тест или упал, и сам отправит результат в TestY.

Только вот я — инженер по ручному тестированию, и максимум, что я писал, — это bash-скрипты для автотестов. Но, раз уж болит, пора пробовать. 

Этап 1: bash-клиент и файл-маркер

Я назвал свой клиент ATS — Automated Testing System. Звучит громко, а на деле это обычный bash-скрипт, который должен уметь: логиниться в TestY, забирать список тестов из тест-плана в формате JSON, запускать тесты по очереди и отправлять статусы и файлы обратно в TestY.

Тут же встал вопрос: как понять, успешно ли завершился тест, описанный скриптом? Ведь он может быть написан на чем угодно, делать что угодно и даже не возвращать понятный exit code. И вообще быть не моим, а сторонним — у нас есть такие скрипты от вендоров.

Я ввел правило:

Действие скрипта

Описание

Статус

Дошел до последней строки кода, в конце создал файл с именем «PASSED_что-то»

Однозначно прошел успешно

PASSED

Создал любой другой файл

Нужно проверить

VERIFY

Ничего не создал

Не дошел до конца и упал из-за некоего условия 

FAILED

Был прерван вручную по Ctrl+C

— 

INTERRUPTED

Это стало моим основным подходом. Вся логика работы ATS выстроилась на файл-маркере. Для начала вполне достаточно, ведь это просто, но работает. Даже для скрипта в 10 000 строк кода достаточно в самом конце добавить строчку создания файла с именем PASSED_<timestamp>.txt. Если скрипт дошел до конца, значит, он не упал в процессе и выполнился успешно. Никакой магии, никаких зависимостей от языка или фреймворка.

Почему именно файл-маркер?

Можно было, конечно, смотреть на exit code. Но на практике это оказалось ненадежно. Один скрипт завершается с кодом 0, но не создает отчет. Другой падает с ошибкой, но оставляет полезный лог. Третий вообще интерактивный, и его нельзя просто «запустить и забыть». 

Файл-маркер дал однозначную точку принятия решения:

  • Есть PASSED_* → PASSED.

  • Есть что-то другое → VERIFY (пользователь решит, что это за сущность).

  • Ничего → FAILED.

  • Ctrl+C → INTERRUPTED.

Что угодно можно запустить как тест для TMS.

TestY позволяет на лету создать свои кастомные статусы, это очень удобно. Что я и сделал: добавил атрибуты VERIFY и INTERRUPTED для своего проекта в TMS. Это позволило встроить в систему любой внешний скрипт, даже без знания его логики. Надо просто добавить строку кода, которая будет создавать файл PASSED_<timestamp>.txt в конец — и все работает.

И да, файл может быть пустым, — тогда это просто сигнал. А может содержать полноценный отчет, архив логов или скриншот. Ведь скрипт так или иначе собирает или преобразует какие-то данные, достаточно сложить их в файл. ATS не разбирается в содержимом — он смотрит только на имя.

Как связать тестовый кейс и скрипт

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

В первую очередь добавил поле shortname, где указывался путь до исполняемого скрипта на тестируемой системе (например, /opt/tests/nvme_tcp.sh или /tmp/mytest.py). Если shortname пуст, клиент скачивает скрипт из вложения. Приоритет всегда у shortname, потому что вложение может устареть, а путь можно вести прямо из Git. Это оказалось удобно при совместной работе.

В процессе родилась философия, которой я придерживаюсь до сих пор:

Один тест — один скрипт — один результат.

Она кажется очевидной, но действительно спасает от хаоса. Если у вас сложный сценарий из пяти этапов, вы не пишете один монолитный скрипт. Вы делаете пять тест-кейсов и пять скриптов, каждый со своим маркером. Это делает результаты прозрачными, а отладку — локальной. Например, если мне надо сначала настроить ресурсы на СХД, потом что-то с ними сделать, а затем удалить, я разделяю это на три отдельных теста-скрипта.

Итак, первый релиз ATS-клиента для TestY выглядел так:

bash ats-1.0.bash --user myuser --password mypass --testplan 12345

  1. Лог��нимся в TestY под myuser и mypass.

  2. Берем список тестов-скриптов из тест-плана с указанным ID или скачиваем вложения, формируем runlist.

  3. Выполняем runlist по порядку.

  4. После каждого выполненного скрипта смотрим, какие файлы создались или не создались в директории.

  5. Добавляем нужный статус и вложение в TestY.

И это заработало. Медленно, костыльно, но заработало. И главное, обычные скрипты, которые я мог видеть первый раз, уже сами отчитывались о себе в TestY. Но первая версия жила недолго. Уже через пару недель я наткнулся на проблемы, которые было мучительно решать в bash:

Парсинг JSON: jq помогал, но при вложенных структурах все превращалось в ад из-за цепочек POST-GET запросов к API TestY.

  • Обработка ошибок: set -e не спасал, когда скрипты вели себя странно.

  • Работа с API: каждый запрос — отдельный curl, каждый ответ — временный файл.

  • Таймауты: приходилось городить timeout + фоновые процессы + обработку завершения.

Особенно больно стало с пагинацией. TestY по умолчанию отдает только 100 тестов за раз. Чтобы получить все, нужно делать несколько запросов, вытаскивая next_page из ответа. В bash это выглядело как цикл из curljqifcurl… и так далее. Код раздувался, читать его было невозможно.

Пора было переходить на Python.

Этап 2: переход на Python 

Когда переписывал ATS на Python, по-настоящему оценил мощь готовых решений. Нужен HTTP-клиент? Бери requests. Нужен CLI с флагами? argparse справится за 10 строк. Нужен цветной лог? colorama + logging. Нужна обработка JSON? Он встроенный.

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

Даже асинхронную загрузку можно было реализовать через aiohttp — это ускорило работу ATS в несколько раз. Теперь тестовый план из нескольких сотен тестов загружался за пару секунд. К тому же я добавил возможность фильтрации запуска тестов через передачу флагов статусов: --passed, --failed, --verify, --interrupted.

По умолчанию все тесты в TestY стоят в статусе Untested. После того как ATS с ними провзаимодействовала, статус так или иначе изменялся на другой. Поэтому логика стала такая: по умолчанию запускаем все Untested-тесты. А если надо перепройти, например, тесты в статусе Failed, указываем соответствующий флаг --failed.

Также я добавил запуск одного конкретного тестового кейса в тест-плане через параметр --testcase.

python3 ats-2.0.py --user myuser --password mypass --testplan 12345 --failed --passed --verify --interrupted

Новая версия стала быстрее за счет парсинга JSON в памяти, а не через файлы. Чище, потому что вместо цепочки команд появился структурированный код. И гибче, ведь я добавил флаги --passed, --failed, --testcase для запуска одного теста. Но главное — она стала масштабируемой. Теперь я мог не просто запускать тесты, а думать о том, как они управляются. ATS-клиент становился все более гибким и универсальным. 

Этап 3: как ATS внедряли в проекты KVADRA

Настоящий толчок к развитию мне дал QA-митап в Питере. Я выступил с докладом про ATS, и после ко мне пришли коллеги из отдела тестирования планшетов KVADRA. У них была пачка из 200 тестов, которые выполнялись «ручными» QA-специалистами. Они запускали задания через Jenkins, вручную проверяли, что получилось, шли в TestY и ставили статусы. В общем, та же боль, с которой я начал.

Моя идея клиента для TestY им понравилась, и коллеги попросили адаптировать ее для них. Пригодились и пагинация, и флаги запуска.

Мы немного изменили статусы — тестировщикам KVADRA не нужны были Verify и Interrupted. Пришлось добавить ID проекта в клиент, поскольку это была уже другая ветка в TestY, переход в директорию, где находился скрипт, и прочие мелочи. К тому же стали использовать теги TestY: из 2 000 тестов только 200 были автоматическими, а перекраивать тестовые планы не хотелось. Поэтому мы стали использовать тэги в Testy, их можно создавать на лету. Это помогло разделять и помечать нужные автотесты в одном тест-плане.

Также я добавил два новых статуса в TestY — «ATS Queued» и «ATS Running». В начале выполнения тестового плана добавляем для всех тестов результат со статусом «ATS Queued» (ставим в очередь), а для текущего теста добавляем результат «ATS Running» — помечаем как выполняющийся прямо сейчас. Получилась обновляющаяся в прямом эфире очередь заданий в TestY с пометкой, какой тест выполняется прямо сейчас.

Через те же теги я реализовал выполнение тестов с перезагрузкой SUT. Если у теста был тег «Reboot», то после его выполнения ATS ставила себя в автозапуск с сохранением параметров, перезагружала систему и при логине снова запускала себя, используя тот же тест-план. Ведь в TestY все тесты для прохождения уже стоят в статусе «ATS Queued». Дешево и сердито. Но при этом эффективно.

Через месяц у коллег из KVADRA все заработало. Мы встроили ATS в их уже готовые задачи Jenkins, они добавили по одной строчке на создание файлов-маркеров в свои скрипты и вуаля — решение заметно сократило ручную работу. Почти сразу они стали экономить по 40 часов в месяц и полностью освободили одного специалиста от рутинной работы. Всегда приятно видеть, как что-то действительно помогает и выходит за рамки pet-проекта.

Этап 4: рождение ATS Studio

«А что, если запускать ATS из браузера?» — однажды подумал я.

CLI — удобно, если ты в терминале. Лично я тот самый человек, который любит графический интерфейс, и, скорее всего, я тут не одинок. Еще в самом начале, когда начал писать ATS на bash, я думал, как было бы здорово, если в TestY была кнопка «Запустить тестовый план». Нажимаешь — и ATS-клиент запускается на нужной машине.

Поговорил с разработчиками TestY — идея хорошая, но реализация откладывается. Тогда я решил: сделаю свою кнопку. Ведь все, что нужно, — запустить ATS-клиент на удаленной машине с правильными параметрами. Передать ему логин-пароль, ID проекта и тест-плана, а клиент уже сам все сделает. 

Так родилась идея ATS Studio — веб-интерфейса для выполнения ATS-клиента. Очень быстро я понял, что ATS-клиенту не нужен веб-интерфейс, зато он нужен серверной части. То есть делаем отдельный сервер, который через web UI получает различные параметры и настройки для доступа к удаленной машине, запускает там ATS, ��ак он есть в терминале.

 

Задумка была простой: три блока на HTML-странице:

  • Подключение к SUT — IP, логин, пароль, пароль root. Так мы подключимся по SSH и сможем делать на SUT что угодно.

  • Подключение к TestY — логин, пароль, ID проекта и тест-плана.

  • Запуск — большая зеленая кнопка.

Но, чтобы это заработало, нужно было настроить SUT: установить зависимости, скопировать скрипты, настроить виртуальное окружение Python. И запустить клиент так, чтобы видеть, что происходит.

Для настройки я выбрал Ansible — он отлично справляется с разными дистрибутивами Linux. В основном мы работаем с отечественными: РЕД ОС, ATL Linux, Asta Linux. Один плейбук и скрипт автоконфигурации — и «голая» машина за две минуты превращается в готовую тестовую среду. Ставим нужные пакеты, настраиваем env, время, отключаем SELinux и прочее.

А вот с отображением хода выполнения возникли сложности. Сначала пробовал писать лог в файл и «транслировать» его на веб-страницу. Но это было медленно, неинтуитивно и громоздко. Хотелось видеть полноценный удаленный терминал на веб-странице, чтобы можно было с ним взаимодействовать, использовать тот же Ctrl +C. А все способы трансляции логов исключали интерактивность.

И тут я вспомнил про ttyd — легкий веб-терминал. А что, если запускать ATS-клиент не напрямую, а внутри ttyd на SUT. Тогда вывод будет доступен по HTTP. Попробовал — и это сработало идеально. Теперь при нажатии «Запустить» открывается новая вкладка с подключением к запущенному ttyd на удаленной машине. Вижу, как идут тесты. Могу нажать Ctrl+C, если что-то пошло не так. Чувствую себя, как будто сижу прямо на SUT. Идеально.

Это, пожалуй, мой любимый момент во всем проекте. Реализовать терминал в браузере получилось, просто обернув команду запуска ATS в ttyd,— для меня это было похоже на магию.

Этап 5: ATS Studio для всего

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

Это означало: SUT в «глухой» подсети не может напрямую общаться с TestY. А значит, ATS-клиент на ней просто не сможет отправить результат. Поэтому раньше все тестовые машины были в одной с TestY подсети.

Когда появилась ATS Studio, решение этой проблемы пришло почти сразу. Развернем ATS Studio в подсети, откуда есть доступ к TestY, добавим интерфейсы в нужные изолированные подсети и будем использовать его как простой HTTP-прокси. Для этого надо добавить на ATS-клиенте новый параметр запуска --proxy и использовать его, если клиент в изолированной подсети.

Все запросы к TestY (через REST API) в таком случае идут не напрямую, а через squid на ATS Studio, который просто перенаправляет их дальше. Так мы решили проблему сетевой изоляции без VPN, маршрутизации и танцев с бубном. И теперь можем запускать тесты абсолютно откуда угодно — лишь бы был SSH-доступ до SUT и ATS Studio видела эту подсеть. 

Как выглядит архитектура ATS

Что

ATS Studio

ATS-клиент

Ansible

Роль

Flask-приложение

Python-скрипт

Универсальный «настройщик»

Особенности

Отдает веб-интерфейс.

Принимает данные от пользователя (подключение к SUT, подключение к TestY).

Запускает Ansible для подготовки SUT.

Копирует туда ATS-клиент и скрипты, если используется shortname в тестовых кейсах.

Запускает ATS-клиент внутри ttyd.

Выводит подключение к ttyd на SUT в отдельной вкладке.

Подключается к TestY напрямую или через прокси.

Загружает тесты с учетом пагинации и тегов.

Для каждого теста ATS-клиент делает следующее:

— запускает скрипт по пути из атрибута shortname или из локальной папки после скачивания из вложения,

— ждет завершения выполнения скрипта,

— ищет файл-маркеры созданные после начала выполнения скрипта,

— отправляет статус и файл в TestY (если PASSED).

Определяет дистрибутив (Astra/ALT/РЕД ОС).

Устанавливает нужные пакеты (iscsi-initiator-utils, nvme-cli, stress-ng, python3-pip и т. д.)

Создает виртуальное окружение для ATS-клиент.

Отключает SELinux/AppArmor (если мешают).

Копирует скрипты из репозитория.

Все это — без единого хардкода. Все изменяемые параметры передаются через CLI или веб-форму. Особенно всякие креды — исключительно в параметрах, а не в коде.

Визуальная эстетика: почему это важно

«Во-первых, это красиво». Когда я показываю сейчас ATS коллегам, всегда начинаю с этих слов. 

Я взял фирменные шрифты, цвета компании, колонтитулы, вынес стили CSS в отдельный файл. Это не «сырой» Flask-прототип в стандартных серо-белых тонах. Это законченный продукт, которым приятно пользоваться.

Я потратил время на то, чтобы интерфейс вызывал доверие. Потому что, если инструмент выглядит как костыль, люди не захотят в него верить. А если он выглядит профессионально, даже в случае ошибки подумаешь: «Наверное, проблема не в системе, а в моем скрипте». Удобно :)

И существует огромная разница между демонстрацией решения через CLI и симпатичный web UI. 

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

Как изменилась работа с TestY

Я полностью исключил ручную работу с результатами тестов в TestY — теперь только изучаю их. Создаю тестовый план, добавляю, как в корзину, нужные тесты и через ATS Studio запускаю одной кнопкой пачку скриптов. Ноль времени — на обновление статусов и вложений.

Раньше я боялся запускать длинные тесты ночью — вдруг что-то пойдет не так. Теперь нажимаю кнопку, иду домой, а утром в TestY уже все отражено. Даже если ttyd на тестовой машине упал, сам ATS-клиент прекрасно работает.

Раньше коллеги из других отделов просили «просто скрипт», чтобы запустить у себя. Теперь — даю ссылку на ATS Studio, IP тестовой машины и ID тестового плана. Ноль времени на живую демонстрацию решения о на тестовом стенде.

А в следующем году, когда мы допишем свои автотесты и автосьюты, планируем выйти на 90% автоматизации всей нашей работы. ATS — ключевой элемент этого процесса. Все остальное — это писать скрипты для ATS. 

Пример интерфейса TestY с моей автоматизацией
Пример интерфейса TestY с моей автоматизацией

Теперь в TestY все стало красивее, понятнее. Теги пришлись к месту. Автоматизация заставила переработать и наш подход к тестированию,  усовершенствовать методики.

Windows HLK как образец

Когда я начинал, то вдохновлялся Windows HLK — фреймворком от Microsoft для автоматизированного тестирования оборудования. Мне нравилось, как там все собрано в одном месте: установка клиента, запуск тестов, мониторинг, отчетность. Только там сам набор тестов определяется компонентами оборудования, которые нашел клиент HLK. И это отличная мысль, куда двигаться дальше.

В свое время я много занимался сертификацией оборудования под Red Hat, VMWare, Ubuntu, SLES. Но HLK, на мой взгляд, — самый удобный и��струмент. Тот самый user-friendly, на который я так или иначе ориентировался в своей работе с ATS.

Мне всегда хотелось, чтобы в сертификационном тестировании с отечественными вендорами Linux было что-то похожее на HLK. И идеология DIY (Do It Yourself) тут вполне применима.

Вот и получилось, что ATS Studio — это мой HLK для мира Linux и отечественных ОС, а также для работы моей и не только команды. Я планирую активно распространить свою логику автотестирования среди коллег, и моим флагом в этом походе выступит уже существующий и рабочий вариант ATS Studio. С той лишь разницей, что он рос не сверху вниз, а снизу вверх — из реальной боли, bash-скрипта и простого нежелания ставить статусы в TestY вручную.

Я пока не выложил решение в open source, но планирую заняться этим в следующем году. Подписывайтесь на техническую рассылку для QA-специалистов — из нее вы первыми узнаете о развитии решения и получите ссылку на репозиторий.

Итог: я не разработчик и вряд ли им стану

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

За все время, что я работал с TestY, только первые пару недель я сидел в dev-ветке нашей системы. Очень быстро я переехал в продуктовую и ни разу ничего не сломал. Swagger помогал в понимании, как и какие запросы делать к API, а простая цепочка POST-GET-запросов не давала что-то уронить.

Пока я шел от боли к решению, сам не заметил, как научился:

  • писать на Flask,

  • проектировать клиент-серверные взаимодействия,

  • работать с REST API и прокси,

  • думать об архитектуре, а не только о скриптах,

  • отстаивать свое видение процесса.

И главное — создал инструмент, который реально используется, экономит время и делает нашу работу чище. А еще он красивый. Я бы не провернул этот фокус, если бы не TestY. Именно открытость и простота этой TMS помогла мне погрузиться в процесс разработки. Теперь, если что-то имеет REST API, но не имеет нужного мне функционала, я легко смогу сделать очередную прокладку, чтобы делать именно то, что мне нужно.

Что такое TestY? Познакомьтесь с TMS в статьях от разработчиков продукта:

→ TMS на замену TestRail: писали для себя, а выложили в open source

→ Улучшение навигации и рост производительности: что изменилось в системе управления тестированием TestY 2.0

→ Читаем под одеялом с фонариком: темная тема и документация в ТМС TestY 2.1