Рекомендация
Как задавать шаги автотеста без ложных падений
Как задавать шаги автотеста без ложных падений
Рекомендация для авторов шагов Playwright в ComplexQA: как собрать импорт, COMMON, URL и Target так, чтобы запуск падал только на реальном расхождении с экраном.
Зачем
Воркер выполняет шаги буквально. Относительный goto всегда берёт стартовый домен запуска, а не текущую вкладку. waitForURL и toHaveURL разбирают Value по-разному. Импорт JSON принимает узкий набор полей. Из-за этого отчёт показывает FAILED на шаге, хотя нужный экран уже открыт, или наоборот: toHaveURL зелёный при странице 404.
Как устроить работу
- Повторяемый вход оформите автотестом вида
COMMON. Проверяемый экран - отдельныйCASE. На карточкеCASEукажите предшественника и привяжите тестовый аккаунт. УCOMMONаккаунта нет: шагиTEST_ACCOUNTчитают аккаунт этогоCASE. Порядок: Когда использовать COMMON и CASE. - После импорта JSON смените вид на
COMMONвручную. Импорт не принимаетpre_autotest_case_idsи вид.COMMONв очередь запуска не ставьте. - Экраны на том же хосте, что стартовый домен, храните в репозитории объектов относительным путём (
/web/ru/user/auth/login). Экраны на поддомене команды - полным URLhttps://{slug}.хост/…. Подтверждённый корень покрывает свои поддомены. На шагеgotoвыберите страницу каталога; Value оставьте пустым. - Для
waitForURLзадавайте Playwright glob (**/web/ru). ДляtoHaveURLзадавайте/pattern/flags(исполнитель собирает регулярное выражение) или glob без хвоста**сразу после последнего сегмента пути. - Target должен находить один узел. Если
ROLEс одним именем даёт два heading, смените kind наCSS. - Проверяйте то, что видно после предыдущего шага, а не экран, который был вчера. Скриншот - опция запуска, не
action_name.
Инструкции действий: goto, waitForURL, toHaveURL, toBeVisible.
Чего избегать
Каждый подраздел - одно ложное падение: что видно в отчёте, почему так, что поставить в шаге.
Импорт отклоняет value_source_type
В отчёте импорта. Unknown field value_source_type / value_source_field. Кнопка создания пропускает только валидные элементы массива.
Почему. Контракт импорта автотестов принимает у кейса autotest_case_title, autotest_case_description, autotest_case_status, autotest_steps. У шага: sort_order, action_name, target, value_text, timeout_ms. Поля карточки шага (value_source_type, value_source_field, object_repository_page_id, test_account_id, pre_autotest_case_ids) в JSON импорта не входят.
Как. Импортируйте fill с value_text (для синтаксиса). На карточке шага выставьте источник Value TEST_ACCOUNT и поле login / password. Пароль в JSON не кладите. Тестовый аккаунт привязывайте к CASE.
Вход повторён в каждом CASE
В отчёте. Одинаковые goto + fill + click на входе в десятке результатов. Смена формы входа ломает все кейсы.
Почему. Вид CASE без предшественника сам открывает сессию. Импорт не умеет выставить вид COMMON и список предшественников.
Как. Один COMMON «вход». После импорта смените вид на COMMON, статус READY. На каждом CASE в блоке Предшествующие автотесты укажите этот COMMON. CASE, который снимает форму входа, к этому COMMON не привязывайте: иначе снимок будет уже после входа.
waitForURL с /pattern/flags
В отчёте. page.waitForURL: Timeout … waiting for navigation to "/\/web\/ru\/(?!user\/auth)/" при уже открытом https://хост/web/ru.
Почему. Исполнитель передаёт Value waitForURL в Playwright строкой. Строка /…/ не компилируется в регулярное выражение. Символ ? в glob - один любой символ, lookahead не работает. Навигацию лог показывает, совпадения нет.
Как. Glob, как в инструкции waitForURL: **/web/ru. Регулярное выражение /pattern/flags используйте в toHaveURL.
Glob waitForURL со слэшем, которого нет в адресе
В отчёте. Ожидание **/web/ru/ или шаблона с \/web\/ru\/, получен https://хост/web/ru без слэша после ru.
Почему. Playwright сравнивает с фактическим href. Лишний слэш в шаблоне не совпадает с путём без завершающего слэша.
Как. Пишите glob так, как адрес выглядит в браузере: **/web/ru, не **/web/ru/, если слэша в конце нет.
toHaveURL с glob и хвостом **
В отчёте. expect(page).toHaveURL Expected: "**/web/ru/project/listing**" Received: https://{slug}.хост/web/ru/project/listing. Экран верный, шаг красный.
Почему. У toHaveURL исполнитель прогоняет Value через разбор /pattern/flags. Иначе строка уходит в Playwright как glob. Хвост ** сразу после последнего сегмента (listing**) не совпадает с URL, который на этом сегменте заканчивается.
Как. Для toHaveURL задайте регулярное выражение:
/\/web\/ru\/project\/listing/Либо glob без хвоста: **/web/ru/project/listing. Не копируйте в toHaveURL тот же приём «обернуть путь в **…**», который сработал у waitForURL.
toHaveURL смотрит /web/ru/, страница каталога ведёт на /web/en/
В отчёте. Expected: **/web/ru**. Received: https://{slug}.хост/web/en/project/listing. Меню на английском.
Почему. goto с страницей репозитория подставляет путь записи каталога. Проверка URL в CASE должна совпадать с этим путём, включая сегмент локали.
Как. В карточке страницы каталога держите тот сегмент локали, который нужен сценарию (/web/ru/… или /web/en/…). Value toHaveURL повторяет тот же сегмент.
ROLE heading: strict mode, два узла
В отчёте. strict mode violation: getByRole('heading', { name: '…' }) resolved to 2 elements - например h5 шапки и h2 карточки с одним текстом.
Почему. Playwright в строгом режиме запрещает действие, если локатор находит больше одного узла. Kind ROLE + одно имя не различает два heading.
Как. Kind CSS с селектором одного узла (например h2.team-listing__title). Если шаг только подтверждает экран, а следующий клик однозначен, лишний toBeVisible по неуникальному heading уберите.
Относительный goto после смены хоста в COMMON
В отчёте. goto зелёный, на снимке страница 404 «Не найдено». Адрес вида https://webapp.пример/web/ru/project/listing без поддомена команды.
Почему. Относительный путь в goto склеивается со стартовым доменом запуска, не с хостом, на котором закончился COMMON. Клик по команде мог открыть {slug}.хост, следующий goto /web/ru/project/listing возвращает на корень. На корне этого экрана нет.
Как. Не увеличивайте число стартовых доменов. Заведите страницу каталога с полным URL https://{slug}.хост/web/ru/project/listing и выберите её на шаге goto. Подтверждённый корень покрывает поддомен. Подробнее: Страница репозитория и goto.
toHaveURL зелёный при 404
В отчёте. toHaveURL за путь /web/ru/project/listing - PASSED. Следующий toBeVisible по пункту меню - FAILED. Снимок: 404.
Почему. Проверка по пути не видит хост. Тот же путь на корне и на поддомене команды даёт разный экран.
Как. Для toHaveURL включайте хост или поддомен в шаблон (/\/{slug}\..*\/web\/ru\/project\/listing/ или glob **://{slug}.хост/web/ru/project/listing). Рядом держите toBeVisible по уникальному тексту рабочего экрана: 404 эту проверку не пройдёт.
Проверка экрана, которого после входа уже нет
В отчёте. toBeVisible по h2.team-listing__title («Выберите команду») при снимке списка проектов команды.
Почему. После входа на поддомене команды стартовая страница - рабочая область (listing проектов), не выбор команды. Шаг, написанный под picker, ищет узел с другого экрана.
Как. Стройте COMMON по фактическому снимку шага после click входа. Если picker исчез, удалите клик по команде и проверку заголовка выбора. Проверяйте то, что открылось: карточка проекта, пункт Проекты.
Скриншот как action_name
В отчёте. Импорт или проверка синтаксиса отвергает действие screenshot, либо шага нет в каталоге карточки.
Почему. Снимок экрана - опция запуска («Скриншот при ошибке», «Скриншот результата»), не действие шага. Каталог: Шаг автотеста.
Как. Включите нужную опцию в форме создания запуска автотестов. В шагах оставьте навигацию и проверки.
Локаль по атрибуту lang у html
В отчёте. URL содержит /web/ru/, в логе Playwright узел <html lang="en">. Автор меняет шаги, думая, что открыта английская локаль маршрута.
Почему. Сегмент пути /web/ru/ и атрибут lang на корневом html - разные поля. Проверка URL смотрит href. Подписи меню смотрите на снимке шага.
Как. Сегмент локали в пути страницы каталога и в toHaveURL держите одинаковыми. Для TEXT берите подпись, которая видна на снимке (пункт меню или название демо-проекта), не значение html lang.
Страница не помогла?