Более точный фильтр для автоматизированного UI-тестирования

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

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

Три статьи расходов

Селекторы

  • Редизайн, который ничего не меняет функционально, красит весь набор тестов в красный.

  • Именно сюда уходит большая часть времени на поддержку.

Ожидания

  • Фиксированные задержки медленные и всё равно нестабильные. Правильному ожиданию нужно знать, чего именно ждать.

  • Большая часть нестабильности тестов родом отсюда.

Покрытие, написанное вручную

  • Вы покрываете то, что кто-то написал, а это интересные сценарии, а не те, что ломаются.

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

Три привычки, которые экономят больше всего

  • Опирайтесь на стабильные атрибуты. Отдельный тестовый атрибут вместо CSS-пути. Одно это снимает большую часть поломок от редизайна.

  • Ждите состояния, а не времени. Дожидайтесь элемента или ответа. Фиксированная задержка одновременно медленная и ненадёжная.

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

Почему наборы тестов удаляют

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

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

Покрытие, которое не зависит от времени автора

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

Терминал

npm install -g @testsprite/testsprite-cli
testsprite setup

Дашборд закрывает то же самое для тех, кому не нужна локальная установка, а полный набор команд описан в репозитории CLI.

Размер набора тестов, который остаётся полезным

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

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

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

Запускайте на каждое изменение

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

Где TestSprite меняет арифметику

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

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

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

Сколько UI-тестов нам нужно?

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

Какой процент прохождения тестов считать приемлемым?

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

Нужно ли запускать UI-тесты на каждый коммит?

Обычно правильный ответ — на каждый pull request. На каждый коммит часто слишком медленно, чтобы быть полезным, и такие запуски в итоге отключают.

А что насчёт визуальной регрессии?

Отдельная задача со своей проблемой допусков. Полезна для дизайн-систем, шумна для экранов приложения.

Нужно ли всё ещё ручное тестирование?

Для исследовательского тестирования и всего, где нужно судить, ощущается ли что-то правильным, — да. Для повторения одних и тех же проверок — нет.

Коротко

Покрывайте то, что сломается тихо.

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