сеньорчикОткрыть в Telegram
← вся теориятеория к собесу · Автоматизация тестирования

Автотесты в CI

Автотесты на сервере сборки

Замер: 60 тестов подряд идут 3,01 секунды. На 4 потоках - 0,75 секунды, на 8 - 0,40, на 16 - 0,20. Ускорение почти идеальное. Но те же тесты, если они работают с общими данными, на 4 потоках проваливаются 59 раз из 60. Параллельность даёт скорость только поверх изоляции.

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

// Формулировки: «как автотесты живут в CI?», «как ускорить прогон?», «что делать при падении на сервере?».

Ступени по скорости

CI - сервер, который на каждое изменение в репозитории (общем хранилище кода с историей) сам собирает проект и прогоняет проверки. Смысл в том, что «у меня локально работает» перестаёт быть аргументом: пока не зелено там, изменение не принято.

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

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

CI
сервер, который на каждое изменение собирает проект и гоняет проверки
блокирующий прогон
проверка, без зелёного результата которой изменение нельзя влить

Параллельность и её цена

Главный рычаг времени - параллельный запуск. Набор делят между несколькими исполнителями: замер выше показал почти линейное ускорение, 60 тестов с 3,01 секунды до 0,40 на восьми потоках. На реальном наборе в час это разница между «после обеда» и «через восемь минут».

Но у ускорения есть предпосылка, и она не эстетическая. Те же 60 тестов, если они пишут в одни и те же данные, на четырёх потоках провалились 59 раз из 60: каждый тест видел следы соседей. То есть неизолированный набор при распараллеливании не ускоряется, а разваливается, и вы потратите недели на разбор «загадочных» падений.

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

деление набора
тесты раскладывают между параллельными исполнителями
изоляция как предпосылка
без неё параллельность даёт не скорость, а шквал падений

Отчёты, следы и дисциплина

Прогон на сервере не равен локальному: браузер работает без окна, ресурсов меньше, сеть другая, язык и таймзона тоже. Поэтому при каждом падении собирают следы - скриншот, видео, запись действий, логи сети. Без них у вас есть только строка «120 упало», и день уходит на раскопки.

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

// Дальше - договорённость, без которой всё вышеперечисленное бессмысленно. Красный блокирующий прогон означает стоп: не вливаем, идём разбираться. Если команда неделю смотрит на красное «потом починим», проверки превращаются в декорацию, а следующий настоящий дефект пройдёт незамеченным. И отдельно: пароли и токены тестов берут из хранилища секретов сервера, а не из репозитория, и следят, чтобы они не печатались в лог прогона.

следы падения
скриншот, видео, запись действий и логи - собираются автоматически
договорённость о красном
красный блокирующий прогон = слияние останавливается

Как отвечать: «Как выстроить прогон автотестов на сервере сборки?»

Главный принцип - дешёвый сигнал раньше дорогого, поэтому строю ступени. На каждый коммит гоню проверку оформления кода и юнит-тесты, это минуты. На пул-реквест добавляю проверки через вызовы к серверу и короткий смоук через интерфейс, чтобы ветка не стояла в очереди часами. Полный набор через интерфейс и матрицу браузеров запускаю ночью и перед релизом. Полный набор на каждый пул-реквест - антипаттерн: очередь, ожидание и соблазн влить мимо проверок. Дальше ускоряю параллельностью: я мерил, шестьдесят тестов с трёх секунд ужимаются до четырёх десятых на восьми потоках, почти линейно. Но параллельность работает только поверх изоляции - те же тесты на общих данных в четыре потока провалились пятьдесят девять раз из шестидесяти. Обязательно собираю следы падения: скриншоты, видео, записи, потому что на сервере браузер без окна, другая скорость и другая таймзона, и без артефактов «упало на сервере» не разобрать. И договариваюсь с командой, что красный блокирующий прогон - это стоп слияния, иначе за неделю всё превращается в декорацию.

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

На чём валят

  • Полный набор через интерфейс на каждый пул-реквест - очередь и вливание мимо проверок.
  • Распараллелить неизолированные тесты: 59 падений из 60 и недели разбора.
  • Отчёт «120 упало» без скриншотов и записей - день археологии.
  • Смотреть на красный ночной прогон неделями: проверки превращаются в декорацию.
  • Токены в репозитории или в выводе прогона - секрет утёк, ротировать немедленно.

Проверьте себя

Пять вопросов из банка по этой подтеме. Всего их 12, остальные разбираются в тренажёре.

  1. #ci_tooling1 / 5
    Зачем при падении автотеста сохранять скриншот, видео и логи?
    A)Артефакты нужны, чтобы измерить, сколько времени тест выполнялся до своего падения
    B)Скриншот и видео заменяют собой сам тест, позволяя не запускать его повторно
    C)Артефакты падения показывают, что было на экране и в системе в момент сбоя
    D)Логи сохраняют, чтобы отправить их разработчику вместо оформления баг-репорта
    показать ответ и разбор
    +C)Артефакты падения показывают, что было на экране и в системе в момент сбоя

    // разбор: Тест в CI упал — но почему? Прогон уже завершён, страницы нет, воспроизвести флаки локально удаётся не всегда. Артефакты, снятые в момент падения, восстанавливают картину: скриншот показывает состояние экрана (не прогрузилось, всплыла ошибка, съехала вёрстка), видео — что тест делал перед сбоем, логи (консоль браузера, сеть, серверные) — что происходило внутри. С ними разбор падения — минуты; без них приходится гадать и многократно перезапускать. Поэтому фреймворки и CI настраивают на автоматический сбор этих артефактов при падении (часто только при падении, чтобы не раздувать хранилище).

  2. #ci_tooling2 / 5
    Зачем нужен отчёт о прогоне тестов (например, Allure)?
    A)Отчёт нужен, чтобы хранить исходный код тестов вместе с результатами их последнего прогона
    B)Отчёт автоматически исправляет упавшие тесты и повторно запускает их до прохождения
    C)Отчёт заменяет собой систему баг-трекинга, куда заносят найденные дефекты
    D)Наглядно показать, что прошло и что упало, с шагами и вложениями
    показать ответ и разбор
    +D)Наглядно показать, что прошло и что упало, с шагами и вложениями

    // разбор: Сырой вывод прогона (сотни строк лога) читать тяжело. Отчёт (Allure и подобные) агрегирует результаты в наглядную форму: сколько тестов прошло и упало, какие именно, с шагами каждого теста, вложениями (скриншоты, логи), длительностью, историей стабильности, группировкой по фичам. По такому отчёту команда за минуты понимает состояние сборки: что сломалось, на каком шаге, как это выглядело. Это ускоряет разбор падений и делает результаты прозрачными для всех, включая нетехнических участников. Отчёт обычно формируется автоматически в конце CI-прогона и публикуется.

  3. #ci_tooling3 / 5
    Почему скорость набора автотестов важна для CI?
    A)Медленный набор задерживает обратную связь и разработку
    B)Скорость набора важна лишь для экономии электроэнергии на серверах непрерывной интеграции
    C)Быстрый набор находит больше дефектов, чем медленный, за счёт большего числа прогонов
    D)Скорость не важна: разработчики всё равно продолжают работу, не дожидаясь результата тестов
    показать ответ и разбор
    +A)Медленный набор задерживает обратную связь и разработку

    // разбор: В CI набор — часть цикла разработки: пока он не отработал, изменение не сливают. Медленный набор (десятки минут) растягивает петлю обратной связи: разработчик ждёт, переключается на другое, теряет контекст, а при падении разбирается спустя время. Команды начинают гонять тесты реже и позже, чтобы не ждать, — и поломки копятся. Быстрый набор, наоборот, гоняют часто (на каждый коммит), поломка обнаруживается сразу, чинится по горячим следам, разработка не буксует. Поэтому за скоростью следят: распараллеливают прогон, держат больше быстрых unit и меньше медленных e2e, выносят долгий регресс в nightly, убирают лишние ожидания.

  4. #ci_tooling4 / 5
    Что такое карантин (quarantine) флаки-тестов?
    A)Карантин — это удаление флаки-теста из репозитория до тех пор, пока его не перепишут заново
    B)Нестабильный тест временно выносят из блокирующего прогона и чинят отдельно
    C)Карантин — запуск флаки-теста по десять раз подряд, пока он не пройдёт хотя бы однажды
    D)Карантин — прогон флаки-тестов на отдельном изолированном сервере ради стабильности
    показать ответ и разбор
    +B)Нестабильный тест временно выносят из блокирующего прогона и чинят отдельно

    // разбор: Флаки-тест в основном блокирующем наборе вредит вдвойне: роняет сборку ложными падениями и приучает игнорировать красный статус. Карантин — компромисс: такой тест временно помечают и переносят в отдельную неблокирующую группу. Он продолжает выполняться (его результат виден и трекается), но его падение не блокирует слияние и деплой, пока причину нестабильности не устранят. Так основной набор остаётся заслуживающим доверия (в нём только стабильные тесты), а флаки не теряется из виду и попадает в бэклог на починку. Важно, чтобы карантин был временным с трекингом, а не «кладбищем», куда молча сваливают и забывают проблемные тесты.

  5. #ci_tooling5 / 5
    Почему код автотестов держат в системе контроля версий (git)?
    A)Чтобы автотесты выполнялись быстрее, ведь из git они загружаются оперативнее, чем с диска
    B)Чтобы результаты прогонов тестов сохранялись в истории коммитов для последующих отчётов
    C)Код тестов живёт в git рядом с кодом продукта: ревью, история, ветки и откат
    D)Чтобы запретить разработчикам менять тесты, оставив это право тестировщикам
    показать ответ и разбор
    +C)Код тестов живёт в git рядом с кодом продукта: ревью, история, ветки и откат

    // разбор: Автотесты — это программный код, и к нему применимы те же практики, что к коду продукта. Хранение в git даёт: историю изменений (кто и зачем менял тест), код-ревью (тесты проверяют коллеги, как и продуктовый код), ветвление (тесты новой фичи развивают в её ветке и мержат вместе с ней), откат к рабочей версии при поломке, и синхронность — тесты меняются в одном коммите/PR с кодом, который они проверяют. Часто их держат в том же репозитории, что и приложение, чтобы изменение поведения и обновление теста ехали вместе. Это делает тесты сопровождаемыми и подотчётными, а не разрозненными скриптами на чьей-то машине.

дальше

Теорию прочитали. Навык ставится повторением

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