Зачем нужна автоматизация UI

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

Автоматизация UI-тестирования — это программа, которая работает с приложением так же, как пользователь: открывает страницу, кликает, вводит текст, читает результат — и сама решает, прошла проверка или нет.

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

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

Что автоматизация даёт

  • Скорость и масштаб. Человек прокликивает 40 сценариев регрессии за день. Машина — за 10 минут, и параллельно в четырёх браузерах. Это не «в 5 раз быстрее», это смена порядка: то, что делалось раз в релиз, можно делать на каждый коммит.
  • Повторяемость. Автотест выполняет шаги ровно так же в сотый раз, как в первый. Человек на сотый раз «и так помнит, что там всё работает», и пропускает шаг.
  • Быстрая обратная связь разработчику. Тест упал в pull request — автор чинит баг, пока ещё помнит, что писал. Тот же баг, найденный через две недели ручной регрессией, стоит в разы дороже: контекст потерян, сверху налипли другие изменения.
  • Доказательства. Отчёт прогона, скриншот момента падения, лог шагов, видео. С этим не поспоришь на разборе, в отличие от «у меня вчера не открывалось».
  • Живая документация поведения. Хорошо названный тест test_user_cannot_pay_with_expired_card честнее любой вики: он не устаревает молча, он падает.
  • Разгрузка людей. Освободившееся от рутины время тестировщик тратит на то, что машина не умеет: исследовать, ломать, задавать неудобные вопросы к требованиям.

Чего автоматизация НЕ даёт

Здесь ломается большинство ожиданий менеджмента, и на собеседовании это любят спрашивать.

  • Автотесты не находят новых багов. Автотест — это капкан, поставленный на известного зверя. Он проверяет ровно то, что вы в нём описали, и ничего сверх того. Новые, незнакомые дефекты находит человек в исследовательском тестировании. Автоматизация ловит возвраты старых.
  • Автотесты не оценивают качество, только соответствие ожиданию. Кнопка «Купить» уехала за край экрана, текст наполз на картинку, шрифт стал нечитаемым — тест зелёный, потому что элемент найден и кликается. Человек бы увидел за секунду.
  • Зелёные тесты не равны работающему продукту. Они означают: «проверенные сценарии не сломались». Это гораздо более скромное утверждение, чем кажется на статус-встрече.
  • Автоматизация не бесплатна. Написать тест — это часы. Поддерживать — часы каждый месяц. Инфраструктура (браузеры, стенды, CI-агенты) — деньги.
  • Автоматизация не заменяет тестировщиков. Она перекладывает на них другую работу — более сложную и более квалифицированную.
КритерийРучная проверкаАвтотест
Стоимость первого прогонанизкаявысокая (написание)
Стоимость сотого прогоната же, что первогопочти нулевая
Находит незнакомоеданет
Оценивает удобство и вёрсткудапрактически нет
Устойчивость к изменениям UIчеловек догадаетсясломается
Работает ночью и на 4 браузерахнетда

Регрессия — главный кандидат на автоматизацию

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

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

Хороший кандидат в автотест выглядит так:

  • сценарий стабилен — фича принята, редизайн не планируется;
  • сценарий повторяется — прогоняется минимум каждый релиз;
  • результат детерминирован — «должно быть ровно так», а не «должно выглядеть прилично»;
  • сценарий критичен — регистрация, вход, оплата, оформление заказа (сломается — потеряем деньги);
  • проверять его руками дорого или муторно — 30 полей формы, 12 комбинаций тарифов.

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

Цена поддержки: автотест — это код, который живёт

Посмотрите на типичный тест начинающего автоматизатора. Он даже работает — сегодня.

from selenium import webdriver
from selenium.webdriver.common.by import By
import time

driver = webdriver.Chrome()
driver.get("https://shop.example.com/")
time.sleep(5)  # «подождём, пока прогрузится»

# локатор, привязанный к структуре вёрстки
driver.find_element(By.XPATH, "/html/body/div[2]/div[3]/section/div[1]/button[2]").click()
time.sleep(3)

assert "Корзина (1)" in driver.page_source
driver.quit()

Этот тест умрёт от чего угодно: дизайнер добавит баннер — и div[2] станет div[3]; текст поменяют на «Корзина · 1» — упадёт проверка; сеть в CI притормозит на 6 секунд вместо 5 — упадёт всё. Каждое такое падение — это ложная тревога: продукт исправен, сломался тест. Три-четыре ложные тревоги подряд, и команда перестаёт читать красные прогоны. Именно так автоматизация и умирает — не от того, что её не написали, а от того, что ей перестали верить.

Дальше в курсе мы починим каждую строчку этого примера: заменим XPath по структуре на устойчивые локаторы, time.sleep — на явные ожидания, а page_source — на проверку конкретного элемента. Пока запомните мысль: поддержка — не досадная мелочь, а постоянная статья расходов, и её нужно закладывать в решение.

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

CASES = 40           # тест-кейсов в регрессионном наборе
MANUAL_PER_CASE = 6  # минут на ручную проверку одного кейса
WRITE_PER_CASE = 60  # минут на написание одного автотеста
RUN_SUITE = 10       # минут машинного времени на прогон всего набора
MAINTAIN = 60        # минут на починку набора после каждого релиза

def manual(releases):
    return CASES * MANUAL_PER_CASE * releases

def auto(releases):
    return CASES * WRITE_PER_CASE + (RUN_SUITE + MAINTAIN) * releases

print("релизов | вручную | автотесты | дешевле")
for r in (1, 5, 10, 15, 20, 40):
    m, a = manual(r), auto(r)
    print(f"{r:>7} | {m:>7} | {a:>9} | {'автотесты' if a < m else 'вручную'}")

Результат:

релизов | вручную | автотесты | дешевле
      1 |     240 |      2470 | вручную
      5 |    1200 |      2750 | вручную
     10 |    2400 |      3100 | вручную
     15 |    3600 |      3450 | автотесты
     20 |    4800 |      3800 | автотесты
     40 |    9600 |      5200 | автотесты

Точка окупаемости — примерно пятнадцатый прогон. Если вы релизитесь раз в две недели, автоматизация начнёт возвращать вложенное через полгода. Если катите в прод каждый день — через три недели. А если проект живёт три месяца и закроется — вы просто подарили ему 2400 минут. Поиграйте с числами в примере выше: увеличьте MAINTAIN вдвое (хрупкие тесты!) и посмотрите, как точка окупаемости уезжает вправо.

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

Автотесты не живут сами по себе — они встроены в конвейер разработки. Классическая расстановка сил — пирамида тестов:

УровеньЧто проверяетСкоростьХрупкость
Unitфункцию, класс в изоляциимиллисекундынизкая
API / интеграционныеendpoint, связку сервисовдесятки мссредняя
UI / E2E (Selenium)сценарий целиком, глазами пользователясекунды и десятки секундвысокая

UI-тесты — верхушка пирамиды: самые медленные, самые хрупкие, самые дорогие в поддержке. Отсюда практическое правило, которое отличает инженера от «писателя тестов»: проверяйте на UI только то, что нельзя проверить уровнем ниже. Правила расчёта скидки — это unit-тест. Ответ ручки /api/cart — это API-тест. А вот «пользователь может пройти путь от карточки товара до оплаты» — да, это Selenium, потому что никакой другой уровень не докажет, что фронтенд, бэкенд и вёрстка сходятся вместе.

Типичная схема прогонов: несколько десятков быстрых smoke-тестов на каждый pull request (чтобы не смёржить очевидно сломанное), полный регресс — ночью или перед релизом.

Частые ошибки

  • «Автоматизируем 100 % тест-кейсов». Красивый KPI, который убивает команду: половина кейсов не подлежит автоматизации в принципе, а вторая половина утонет в поддержке. Автоматизируют не «всё», а то, что окупается.
  • Автоматизировать фичу, которая ещё меняется. Пишете тест на экран, который дизайнер переделает на следующей неделе, — оплачиваете написание дважды. Сначала фича стабилизируется, потом её покрывают.
  • Проверять бизнес-логику через UI. Сорок комбинаций скидок, прокликанных браузером, — это час прогона и тонна флаки-падений. То же самое на уровне API — 5 секунд.
  • Лечить флаки перезапуском. «Упал — перезапустим три раза, авось позеленеет» — это не лечение, а обезболивающее: за нестабильным тестом часто прячется настоящий баг гонки в приложении.
  • Не считать стоимость поддержки. В смету попадает написание, а часы на починку локаторов после каждого редизайна — никуда. Через год выясняется, что «автоматизация не взлетела».
  • Ждать, что тесты заменят тестировщиков. Не заменят. Они заменят рутину тестировщиков.

Итоги

  • Автотест — это код: его пишут, ревьюят, хранят в git и чинят. Стоимость поддержки нужно закладывать заранее.
  • Автоматизация даёт скорость, повторяемость, раннюю обратную связь и доказательства; она не находит новых багов и не оценивает удобство.
  • Главный кандидат на автоматизацию — регрессия: стабильные, повторяемые, детерминированные, критичные сценарии.
  • Окупаемость наступает после N-го прогона (в нашем расчёте — около пятнадцатого). Короткий проект, нестабильный UI, разовая проверка — автоматизация вредна.
  • UI-тесты — верхушка пирамиды: проверяйте на них только то, что нельзя проверить unit- или API-тестом.
Проверьте себя
1. Какое утверждение об автотестах верно?
AАвтотесты находят новые, ранее неизвестные баги лучше человека
BАвтотесты проверяют только то, что в них заложено, и ловят возврат старых багов
CЗелёные автотесты доказывают, что в продукте нет дефектов
DАвтотесты оценивают удобство интерфейса и качество вёрстки
2. Какой сценарий — лучший кандидат на автоматизацию?
AРазовая проверка перед демо новой фичи, которую завтра перепишут
BОценка того, что новая анимация выглядит плавной и приятной
CВход и оформление заказа — критичный сценарий, который гоняют каждый релиз
DЭкран, который дизайнер переделывает каждую неделю