TT-QA

Автоматизация · Практика

Как написать автотест, которому можно доверять

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

Сначала реши, о каком поведении тест должен сообщить

Название «проверка заказа» ничего не говорит о результате. Заказ мог создаться, но не попасть в историю покупателя. Или попасть туда с неправильной суммой. У каждого варианта своя причина падения и своё решение для команды.

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

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

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

Один тест держит один понятный сценарий

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

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

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

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

Тест должен запускаться отдельно от соседей

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

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

Браузерная изоляция помогает с куки и локальным хранилищем, но не изолирует базу сервиса. Эта граница особенно заметна в CI: локально тесты идут по одному, а на сервере одновременно пишут в одну и ту же сущность.

Убирай лишние шаги, прежде чем сокращать таймауты

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

Фиксированная пауза заставляет быстрый прогон ждать зря, а медленному может не хватить времени. Жди конкретного состояния: появился заказ, изменился статус, стала доступна кнопка. Таймаут при этом остаётся верхней границей, а не плановой длительностью каждого шага.

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

Не заставляй браузер проверять то, что можно надёжно проверить через API или на уровне функции. UI-тест нужен для связанного пользовательского пути. Расчёт суммы с десятками наборов данных быстрее и понятнее проверить ниже по уровню.

Код теста должен читаться как проверка поведения

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

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

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

Падение должно объяснять, что сломалось

Сообщение expected true, got false заставляет открывать код и восстанавливать весь сценарий. Лучше назвать проверяемое действие и показать фактическое значение: «Заказ 481 не появился в истории покупателя» или «Ожидали сумму 1 200 ₽, получили 1 250 ₽». Числа здесь пример сообщения об ошибке, а не данные реального заказа.

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

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

Автоматизируй то, что помогает принять решение

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

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

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

Поводом для статьи стали принципы автотестов команды VK ID. Здесь они собраны вокруг решения практических задач; про изоляцию и параллельный запуск также есть документация Playwright.

Сообщить о проблеме

Что случилось?