Просто два кота наших тестировщиков, а вы чего ждали?
Просто два кота наших тестировщиков, а вы чего ждали?

Nota bene. Смешно, но ниже описано то, как выглядели тесты Angie и Angie ADC едва ли не полгода назад. Дело в том, что пока наши чудесные девушки писали как они работают, наш отдел тестирования успел подрасти вместе с командой. Добавились тесты SDN, тесты для ФСТЭК версии Angie PRO (коммерческая версия веб-сервера Angie). В этом смысле текст немного устарел, но мы решили, что его интересно оставить для истории именно в таком виде, а через время написать другой и сравнить в формате «было-стало».   

 С уважением, команда Angie Software


Итак, сегодня расскажем вам историю про контрасты в тестировании знакомых продуктов Angie Software. С одной стороны Angie – веб-сервер на языке C, зрелый проект, развивающий идеи nginx (Никакого UI, только конфиги, только хардкор), с другой – Angie ADC, новый комплексный продукт для балансировки нагрузки и управления сетевым трафиком (есть фронтенд и UI) + организация тестирования с чистого листа. Разный статус проектов и разные подходы, но общая цель. Сегодня поговорим про тесты на Perl для Angie и про тесты на Python для Angie ADC. А для начала давайте познакомимся!

О нас

Оксана:

Меня зовут Оксана и я работаю в сфере IT почти 20 лет, из них больше 10 лет пишу на языке Perl. С апреля прошлого года я тестировщик в отделе разработки Angie/Angie PRO в компании Angie Software.

Настя:

Меня зовут Настя, в этом году будет 5 лет работы в сфере IT по специальности QA engineer. В начале пути я была ручным тестировщиком и по совместительству техническим писателем, следующим этапом стала работа в ИБ-компании, где я стала углубляться в изучение сетевой инфраструктуры и кибербезопасности. В 2024 году мне доверили руководство группой функционального тестирования. С конца 2024 года я работаю fullstack-тестировщиком на проекте Angie ADC в компании Angie Software.

Подход к тестированию в Angie Software

Оксана:

Angie — это форк nginx, проект с богатой историей (в прошлом году nginx отметил свое двадцатилетие). В проекте есть свой устоявшийся стиль, который надо соблюдать.

Исторически сложилось (первый коммит в репозитории nginx-tests был 15.08.2008), что тесты в nginx пишутся на языке Perl. За 16,5 лет было написано больше четырехсот тестов и удобный фреймворк – библиотека Test::Nginx. При разработке Angie/Angie PRO мы решили поддержать традицию и продолжили писать тесты на языке Perl. К тому же так проще подтягивать к себе изменения из nginx (и еще одного его форка freenginx).

Вся разработка Angie/Angie PRO ведется на C. Писать unit-тесты для кода на другом языке довольно специфично, поэтому unit-тестов у нас сейчас нет и все тесты функциональные. Тесты пишут как разработчики, так и я.

Тест-кейсы разбиты на .t файлы по директивам или по фичам, еще есть отдельные тесты на некоторые баги. Все .t файлы устроены однотипно: в тесте генерируется конфиг Angie, поднимается веб-сервер Angie, на него отправляются запросы и затем анализируется поведение Angie: смотрим на сам ответ, на логи, на то, на какой из бекендов ушел запрос, и т.д. и т.п. Примеры тестов можно посмотреть в нашем репозитории.

Настя:

Angie ADC — это новый продукт в линейке Angie Software. Такая разработка — это всегда вызов, а так же и отличная возможность сделать всё «по уму» с самого начала.

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

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

Так с чего начать тестировщику в таком случае? Думаю, такой вопрос будет волновать многих QA, кто только начинает свой путь или кто начал работать в стартапе без четко выстроенных годами процессов. Но здесь только мое мнение и опыт, как я делала первые шаги в тестировании совершенно нового продукта.

В таких условиях первое, что нужно — продумать стратегию тестирования. Да, ответственность за качество продукта лежит на всей команде, однако, тестировщик задаёт структуру этому процессу.

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

  • Как устроен жизненный цикл задачи? 

    Понимание того, как ведутся баги и фичи от идеи до релиза: кто ставит задачи, когда они переходят в тест, кто отвечает за проверку и закрытие.

  • Какие типы тестирования планируются?

    Будет ли только ручное? Что и когда автоматизируем? Нужно ли интеграционное, нагрузочное, тестирование безопасности?

  • Автоматизация vs. ручное тестирование?

    Что стоит покрыть автотестами с самого начала, а что лучше проверить вручную, особенно если интерфейс активно меняется.

  • Какое окружение нужно и как с ним работать?

    Какие стенды поднимать, где хранить настройки, как запускать тесты в разных условиях (локально, на dev-сервере, в Docker).

  • Как будем вести тестовую документацию?

    Какой TMS (система управления тестированием) использовать, как оформлять кейсы, где хранить чек-листы и отчёты.

  • Какие инструменты — под какие задачи?

    Какие средства подойдут для ручного тестирования, какие — для API, автоматизации, логов и анализа.

  • Критерии входа и выхода на каждом этапе?

    Когда задача готова к тесту? Что считается «завершённой проверкой»? Как отличить «почти готово» от «точно работает»?

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

Тип тестирования

Ответственный

Автоматизация

Инструменты

Комментарий

Функциональное

QA

Частично (Backend + Frontend)

TestIT (ручные тест-кейсы), Postman, для автоматизации (Playwright, pytest)

Проверка соответствия требованиям. Основные покрытия UI и API в рамках user stories.

Интеграционное

Dev+QA

Частично

Postman, Swagger, pytest, mock-servers

Dev настраивает взаимодействие модулей, QA проверяет сценарии end-to-end

Регрессионное

QA+DevOps

Частично, где возможна реализация покрытия автотестами

Playwright, API/UI/Backend автотесты, Jenkins CI/CD

DevOps помогает в организации стендов для тестирования, QA проверяет, что новый функцинал не повлиял на работу существующей системы. Автоматизируется для ускорения процесса.

Unit-тестирование

Dev

Да

Встроенный инструмент тестирования в Go, Testify, Jest (для UI)

 

Ответственность разработчика за проверку отдельных модулей и их стабильность, изолированно от остальной системы

Нагрузочное тестирование

QA+DevOps

Частично

JMeter, k6, Prometheus

DevOps готовит окружение необходимое для тестирования, QA проводит тестирование (Jmeter, K6), фиксирует и документирует полученные данные 

Smoke/Sanity

QA

Да

TestIT (Тест-кейсы и чек-листы), Postman (для быстрых проверок запросов)

Быстрые проверки на стендах после сборок и фиксов, не требующие взаимодействия разных модулей, обычно проводятся на UI

Мониторинг и уведомления

DevOps

Да

Grafana, Kibana, Prometheus

Настройка оповещений, логов и мониторинга на конечной версии

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

Этап тестирования

Критерий входа

Критерий выхода

Функциональное тестирование

- Утверждены требования к функции

- Разработка завершена и функция готова для тестирования (с описанием от разработчика)

- Подготовлено тестовое окружение

- Составлены тест-кейсы

- Все зависимые модули готовы 

- Build успешно собран и прошел smoke без проверки взаимодействия модулей

- Функциональность соответствует требованиям 

- Все тест-кейсы пройдены (+ добавлены новые, если необходимо в процессе)

- Все критические и блокирующие баги исправлены и функционал проверен повторно.

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

- Если баги не решены, то они согласованы с менеджером

- Подтверждена готовность к регрессу перед релизом

Unit-тестирование

- Логика реализована в отдельных модулях

- Технические требования и поведение известны и понятны

- Подготовлены зависимости и тестовые объекты, имитирующие реальные

- Проект собирается/компилируется

- Нет блокирующих зависимостей от внешних компонентов

- Все написанные Unit-тесты пройдены успешно

- Достигнуто заданное покрытие кода (в зависимости от требований)

- Исправленные найденные дефекты

- Запуск Unit-тестов происходит автоматически создании и изменении pull request, а так же при вливании в мастер

Инфраструктура и стек технологий

Perl против Python: как мы тестируем и что помогает не сойти с ума

Тестирование должно быть со всех сторон
Тестирование должно быть со всех сторон

Оксана:

Как я уже упоминала выше, мы продолжаем писать тесты на Perl. Кстати, Perl жив и развивается. Основные библиотеки, которые мы используем, это Test::More, Test::Deep и самописный тестовый фреймворк Test::Nginx.

Для удобного просмотра результатов тестирования у нас есть самописная утилита командной строки Build Status, написанная на Python.

Для анализа покрытия кода тестами используется утилита lcov, для статического анализа кода — Coverity Scan (Angie) и CodeChecker (Angie PRO).

Для автоматизации непрерывной интеграции и непрерывного развертывания мы используем Jenkins.

Настя: 

Тестирование — это не просто потыкать кнопки. Это целая система, в которой важны инструменты, процессы и подходы. Ниже — краткий обзор технологий, которые мы используем для реализации этих процессов:

Для ведения тестовой документации выбрали TestIT. С ним удобно оформлять тест-кейсы, группировать их по разделам, отслеживать результаты и связывать с багами или задачами. Всё под рукой, всё понятно. Так же там есть возможность интеграции с системами баг-трекинга и CI/CD, а так же управление автотестами, но использование данных функциональностей планируется вводить постепенно во внутреннюю инфраструктуру.

Автотесты реализуем на Python с использованием Playwright — он отлично подходит для тестирования веб-интерфейсов: быстрый, надёжный и поддерживает разные браузеры.
 В связке с ним работает Pytest — удобный фреймворк с хорошей поддержкой фикстур и понятной структурой тестов. Чтобы не гадать, «а что упало», используем Allure reports — инструмент для красивых и наглядных отчётов по автотестам. 

Для тестирования API под рукой всегда Postman или Insomnia. Оба инструмента просты в использовании, позволяют сохранять запросы, добавлять проверки и анализировать ответы. Выбор — по настроению и задаче.

Иногда нужно протестировать продукт в «чистом» окружении или на другой ОС — в таких случаях помогает Virtual Box/VMware Workstation. Поднимаем виртуальные машины и проверяем, как ведёт себя приложение вне основной среды.

Когда возникает необходимость посмотреть, что происходит «под капотом» в сети — выручает Wireshark. Он помогает провести глубокий анализ сетевого трафика или выявить потенциальные угрозы — отследить пакеты, выявить подозрительную активность или просто понять, почему что-то тормозит.

Процесс обеспечения качества ПО

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

В процессе обеспечения качества участвует не только QA
В процессе обеспечения качества участвует не только QA

Оксана:

В Angie/Angie PRO процесс обеспечения качества ПО выглядит следующим образом:

  1. Постановка задачи. 

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

  2. Разработка.

    От нескольких дней до полугода в зависимости от задачи уходит на написание кода. 

  3. Ревью кода. 

    • Ручное (коллегами): на ревью уходит от нескольких минут до нескольких месяцев, иногда бывает более 10 итераций – ревью очень серьёзное и дотошное.

    • Автоматическое:

      • Статический анализ — набор процессов для поиска дефектов и уязвимостей исходного кода. Проверка запускается при каждом пуше в продовую ветку.

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

  4. Тестирование.

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

  5. Документирование.

    Идет в параллели с разработкой.

  6. Релиз.

    Мажорные релизы выходят раз в квартал, минорные при обнаружении багов.

  7. Непрерывная интеграция и доставка (CI/CD).

    Все тесты прогоняются на ОС из списка. Для этого командой технической поддержки развернута целая инфраструктура: есть специальные выделенные сервера на которых создаются виртуалки и собираются бинарники Angie/Angie PRO. Для прогона тестов на всех ОС нужно запушить код в специальный тестовый репозиторий angie-try – пуш запускает хук в Jenkins. Также тестирование запускается при пуше в продовую ветку.

  8. Тестирование совместимости со сторонними модулями.

    Обеспечивается командой технической поддержки.

    • Все сторонние модули проходят минимальную проверку: производится установка из репозитория, подключение к конфигурации.

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

    • Большая часть сторонних модулей была протестирована в ручном режиме нашими инженерами – это нашло отражение в документации

Настя:

В Angie ADC процесс обеспечения качества пока ещё формируется и подстраивается под реалии проекта и текущие задачи. Тем не менее, уже сейчас можно выделить общую структуру, которой мы придерживаемся.

  1. Постановка задачи

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

  2. Разработка

    Разработчики по негласной договорённости с QA описывают в комментарии к задаче, что делает новая функция, как она должна работать и на какую ветку смотреть, чтобы можно было её протестировать (тестировщик всё-таки не экстрасенс). Такая прозрачность экономит время и упрощает последующую проверку. У тестировщика меньше вопросов – у разработчика хорошее настроение :)

  3. Тестирование

    Я читаю описание, которое оставил разработчик, и на его основе прикидываю план тестирования. Тест-кейсы оформляю в TMS, а дополнительные идеи по проверкам часто появляются уже в процессе.
     Для запуска тестов использую Docker, вручную подтягивая обновления из Git. Иногда — стенд, максимально приближенный к боевому окружению. Он часто помогает лучше отловить баги, особенно при сложной интеграции.

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

  4. Документирование

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

  5. Релиз и регресс-тестирование

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

Процесс регресса делится на несколько шагов:

  1. Подготовка

    Проверяем, что все задачи, запланированные к релизу, завершены. Старые баги (технический долг) по возможности закрыты. Я актуализирую тестовую документацию и формирую тестовый план на основе Changelog — определяю, какие кейсы войдут в проверку.
     DevOps настраивает окружение, максимально приближенное к версии для клиента, чтобы поведение системы было предсказуемым.

  2. Проведение тестов

    В это время замораживается разработка. Из ветки master собирается финальный образ с нужными компонентами и зависимостями.
     На этом этапе я запускаю тесты по плану: ручные проверки, автотесты, проверка специфических требований вроде кроссбраузерности. Цель — удостовериться, что система работает стабильно и ничего не «поехало».

  3. Анализ результатов

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

  4. Ретест и доработки

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

Финальный штрих

Когда всё протестировано и согласовано, собирается финальная сборка. Перед ее выпуском проводится smoke-тестирование — быстрый прогон по основным сценариям, чтобы убедиться, что всё на месте и ничего не потерялось.

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

Какие ошибки нашли?

Оксана:

Обычно я пишу тесты к новой фиче, когда ее код уже написан. К этому времени многие ошибки уже удается отловить в процессе ревью и исправить. К моменту готовности тестов ошибки обнаруживаются не часто (наши разработчики молодцы, и ревью очень серьезное). Какие-то ошибки находятся при прогоне кода в try-репозитории. До релиза ошибки доходят очень редко. Но если это вдруг случается, мы обязательно покрываем эти сценарии тестами.

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

При помощи статических анализаторов в основном находятся ошибки типа переполнения буфера и утечки памяти. Каких-то особо интересных случаев мы не находили и срабатывания в основном ложно-положительные (как я уже писала выше, наши разработчики молодцы). Но отчеты мы смотрим регулярно в качестве гигиены. Хоть заразы и не находили, руки надо мыть все равно :)

Настя:

Как пользователь сам себя удалил — или с чего началось тестирование

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

Как это было? 

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

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

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

Но это то, что касается UI, а что же происходит за кулисами?

Спустя несколько месяцев после старта разработки я всё глубже погружалась в тестирование backend-части продукта — именно на неё стал приходиться основной объём новых функций и логики.

Одним из самых непростых этапов оказалось тестирование протокола VRRP (Virtual Router Redundancy Protocol) — механизма виртуального резервирования устройств. Этот функционал отвечает за то, чтобы при сбоях в сети пользователь не терял подключение благодаря быстрой и автоматической передаче управления от одного устройства к другому.

Тестирование VRRP — это целый пласт сложных сценариев:

  • проверка работы устройств в связке с использованием одного виртуального IP-адреса, который «переезжает» между машинами при смене роли Мастера;

  • резервирование без потери доступа: при падении основного узла доступ к ресурсам сохраняется;

  • тестирование приоритетного голосования — чтобы устройство с наивысшим приоритетом автоматически становилось Мастером;

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

Это не просто "прогнать сценарии" — нужно продумывать поведение системы на уровне взаимодействия узлов, временных задержек, смены ролей и аварийных ситуаций.

Конкретно при этих проверках и было набольшее количество ошибок и фиксов. Причем чинилось одно — ломалось другое.

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

Планы

Оксана:

  • Довести покрытие кода тестами до 85% (сейчас 76,8). До 100% довести не получится из-за наличия т.н. «мертвого» кода и сложности воспроизведения некоторых ошибок. Это тема для отдельной статьи.

  • Внедрение фаззинг-тестирования. Фаззинг – это условно-рандомная генерация конфига и проверка, что Angie не падает – падать он не должен даже с плохим конфигом.

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

  • Ускорение тестов (сейчас выполнение всех тестов на всех платформах занимает примерно 45-70 минут). Хотелось бы уменьшить это время хотя бы в два раза.

Настя:

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

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

  • Контроль релизов (в идеале иметь план релизов, так же версионность внутри спринта, чтобы понимать в какой версии и что изменилось, чтобы была возможность сделать откат).

  • Процесс регулярного регресс-тестирования.

  • Своевременная доработка тест-кейсов и чек-листов.

  • Увеличение покрытия функционала автотестами, в данный момент покрыто примерно 40% функционала, так же необходимо добавить тесты для проверки API.

  • Контроль автотестов в ci/cd (сейчас реализован функционал «ночных» проверок, при изменении функционала – падает тест, с утра можно оперативно поправить недоработку).

  • Завести страничку с changelog в вики, чтобы прикреплять задачи с доски и отслеживать, что было реализовано за это время, а так же в таком виде будет удобнее сравнивать с дорожной картой разработки для понимания дальнейших действий по реализации.

  • Расширение команды тестирования.
     


PS. Вывода не будет. Хотя нет, один будет. Почему то тестировщики считают, что их работа скучна, а рассказывать о ней —  харам. А на наш взгляд это одна из самых полезных и интересных работ в индустрии. Если хотите присоединиться к группе тестировщиков наших продуктов (а у нас их не 1, и не 2), напишите нам на адрес hr@wbsrv.ru, Вместе интереснее!

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


  1. Nickmob
    18.07.2025 07:33

    Ну как это Angie - никакого UI? A Console Light не считается?


    1. VBart
      18.07.2025 07:33

      Просто разработкой Console Light занимается другая команда.