Автоматизация тестирования на Playwright с использованием TypeScript: от нуля до создания фреймворка

Практический курс для QA-инженеров по освоению современного инструмента автоматизации. Обучение включает изучение синтаксиса TypeScript, работу с DOM-элементами и построение масштабируемой архитектуры тестового проекта.

1. Введение в Playwright: архитектура инструмента и настройка рабочего окружения

Введение в Playwright: архитектура инструмента и настройка рабочего окружения

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

Почему Playwright изменил правила игры

Долгое время стандартом индустрии был Selenium. Его работа строится на протоколе JSON Wire (а позже WebDriver W3C), где каждая команда от вашего кода проходит длинный путь: HTTP-запрос к драйверу браузера, преобразование в команду для конкретного движка, выполнение и возврат ответа. Это вносит задержки и делает невозможным глубокий контроль над внутренними событиями браузера.

Playwright использует другой путь. Он работает через протокол CDP (Chrome DevTools Protocol) и его аналоги для Firefox и WebKit. Это дает инструменту «прямой доступ к телу» браузера. Вместо того чтобы стучаться в закрытую дверь и ждать ответа, Playwright находится внутри событийного цикла.

Ключевые архитектурные отличия

  • Единое соединение через WebSocket. В отличие от сотен HTTP-запросов в Selenium, Playwright открывает одно постоянное соединение. Это не только ускоряет выполнение, но и позволяет браузеру самому «сообщать» инструменту о событиях (например, об окончании загрузки сетевого запроса), не дожидаясь опроса со стороны теста.
  • Браузерные контексты (Browser Contexts). Это киллер-фича для параллелизации. Представьте, что вам нужно запустить 10 тестов одновременно. В старых инструментах вам пришлось бы запустить 10 полноценных экземпляров браузера (Chrome), что «съело» бы всю оперативную память. Playwright запускает один процесс браузера, а внутри него создает изолированные контексты. Каждый контекст — это как абсолютно чистая инкогнито-вкладка: свои куки, локальное хранилище и кэш, но при этом они создаются за миллисекунды и потребляют минимум ресурсов.
  • Auto-waiting (Автоматические ожидания). Playwright не просто кликает по кнопке. Перед действием он проверяет набор условий (Actionability checks): виден ли элемент, не перекрыт ли он другим слоем, стабилен ли он (не движется ли в данный момент анимация) и включен ли он (enabled). Это избавляет инженера от необходимости прописывать sleep или сложные wait_until вручную.
  • Из чего состоит Playwright: уровни абстракции

    Чтобы эффективно настраивать окружение, нужно понимать, какими сущностями мы будем оперировать в коде. Архитектуру Playwright можно представить в виде матрешки:

    * Browser (Браузер). Это сам исполняемый файл (Chromium, Firefox или WebKit). Он запускается один раз в начале сессии. * Browser Context (Контекст). Изолированная сессия внутри браузера. Именно здесь реализуется имитация разных устройств (например, запуск теста с разрешением iPhone 13). * Page (Страница). Конкретная вкладка в контексте. Большинство ваших тестов будут взаимодействовать именно с объектом page.

    Особенность Playwright в том, что он поставляется с собственными сборками браузеров. Вам не нужно устанавливать Chrome или Safari на компьютер — инструмент сам скачает нужные ревизии движков, которые гарантированно совместимы с текущей версией библиотеки.

    Подготовка рабочего места: база для TypeScript

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

    1. Node.js — мотор нашей автоматизации

    Playwright — это библиотека для Node.js. Нам нужна версия LTS (Long Term Support), так как она наиболее стабильна. * Зачем это нужно: Node.js позволяет исполнять JavaScript/TypeScript вне браузера, управлять файлами и сетевыми запросами. * Проверка: Откройте терминал и введите node -v. Если версия ниже 16, стоит обновиться.

    2. Visual Studio Code (VS Code)

    Это стандарт де-факто в мире TypeScript. Для работы с Playwright нам критически важно установить расширение "Playwright Test for VSCode" от Microsoft. * Что оно дает: Возможность запускать тесты кнопкой "Play" прямо рядом со строкой кода, визуальную отладку, запись тестов (Codegen) и удобный просмотр логов.

    3. Менеджеры пакетов (npm или npx)

    Мы будем использовать npm (идет в комплекте с Node.js) для установки зависимостей и npx для запуска инструментов Playwright без их глобальной установки в систему.

    Инициализация проекта: пошаговый разбор

    Перейдем к практике. Создайте пустую папку для вашего будущего фреймворка (например, playwright-course) и откройте её в VS Code.

    Введите в терминале команду:

    Эта команда запускает интерактивный помощник. Давайте разберем, какие опции стоит выбрать и почему:

  • TypeScript or JavaScript? Выбираем TypeScript. Это даст нам строгую типизацию, а значит — автодополнение кода (IntelliSense). Вы начнете печатать page. и редактор сам подскажет все доступные методы. Это критически важно для новичков, так как снижает количество опечаток.
  • Where to put your end-to-end tests? По умолчанию предлагается папка tests. Соглашаемся.
  • Add a GitHub Actions workflow? Выберите false для начала, мы разберем это позже в темах про CI/CD.
  • Install Playwright browsers? Обязательно true. Инструмент скачает около 500-700 МБ данных (движки Chromium, Firefox и WebKit).
  • Что появилось в папке проекта?

    После завершения установки ваша структура будет выглядеть так:

    * node_modules/ — «черная дыра» зависимостей. Здесь лежат все библиотеки, которые нужны для работы. Никогда не меняйте ничего внутри. * tests/ — здесь будут жить ваши файлы с тестами (например, example.spec.ts). * playwright.config.tsглавный мозг проекта. Здесь настраиваются таймауты, репортеры, базовый URL сайта и то, в каких браузерах запускать тесты. * package.json — паспорт вашего проекта. Здесь указаны версии библиотек и прописаны скрипты для запуска.

    Глубокое погружение в конфигурацию (playwright.config.ts)

    Файл конфигурации часто пугает новичков обилием кода, но это сердце вашего фреймворка. Давайте разберем ключевые блоки, которые мы будем настраивать.

    Разбор параметров:

    * testDir: Если вы решите переименовать папку с тестами, не забудьте обновить этот путь. * fullyParallel: Playwright умеет запускать тесты очень быстро. Если у вас 100 тестов, он может запустить их в 5-10 потоков одновременно. Но будьте осторожны: если тесты используют одного и того же пользователя (например, меняют ему пароль), они могут мешать друг другу. * use: Это глобальные настройки для всех тестов. Здесь мы задаем baseURL, чтобы в самих тестах писать короткий путь await page.goto('/login') вместо полного URL. * projects: Это настройки окружений. Вы можете описать проект "Mobile" и указать там эмуляцию iPhone, или проект "Production", который будет ходить на боевой стенд.

    Первый запуск и проверка работоспособности

    Чтобы убедиться, что всё настроено верно, запустим демонстрационный тест, который Playwright создал автоматически.

    В терминале выполните:

    Вы увидите сообщение в духе Running 6 tests using 3 workers. Почему 6, если тест один? Потому что в конфиге по умолчанию прописано три браузера (Chromium, Firefox, WebKit), и Playwright запустил наш единственный тест в каждом из них.

    Если вы хотите запустить тесты с графическим интерфейсом (UI Mode), используйте:

    Это откроет мощное окно управления, где можно видеть каждый шаг теста, историю переходов и даже состояние DOM (структуры страницы) на каждом этапе. Это лучший способ для обучения и отладки.

    Проблемы при настройке и их решение

    Даже у профессионалов настройка может пойти не по плану. Рассмотрим типичные «грабли» новичка.

    Конфликты версий Node.js

    Если при установке возникают ошибки Unsupported engine, значит ваша версия Node.js слишком стара. Используйте менеджер версий (например, nvm для Mac/Linux или nvm-windows для Windows), чтобы легко переключаться между версиями. Для Playwright оптимальна любая четная версия Node.js (18, 20).

    Отсутствие системных зависимостей (особенно на Linux)

    Браузеры — это сложные программы. Им нужны системные библиотеки для отрисовки шрифтов или работы с графикой. Если вы запускаете Playwright на «голой» Ubuntu, тесты упадут с ошибкой отсутствия .so файлов. Решение: выполнить команду:

    Она доставит в операционную систему все необходимые кодеки и библиотеки.

    Прокси и корпоративные сети

    Если вы работаете в офисе с жесткими настройками безопасности, команда npm init playwright может зависнуть на скачивании браузеров. Решение: Настройте прокси в терминале или попросите системных администраторов открыть доступ к доменам playwright.azureedge.net.

    Роль TypeScript в нашем стеке

    Многие задаются вопросом: «Зачем мне TypeScript, если я только учусь? Не проще ли на JavaScript?». Короткий ответ: Нет, не проще.

    В JavaScript вы можете ошибиться в названии метода, например, написать page.clik() вместо page.click(). Вы узнаете об ошибке только тогда, когда запустите тест и он упадет через 30 секунд. TypeScript подсветит эту строку красным еще в процессе написания. Он работает как строгий, но полезный редактор, который проверяет:

  • Существует ли такой метод у объекта?
  • Правильного ли типа данные вы передаете (строку, число или объект)?
  • Не забыли ли вы await перед асинхронной операцией (что является самой частой ошибкой в автотестах)?
  • Весь наш дальнейший путь будет построен на использовании интерфейсов и типов, которые предоставляет Playwright. Это сделает ваш код профессиональным, читаемым и легким в поддержке.

    Изоляция и чистота: философия Playwright

    Завершая настройку, важно принять философию инструмента. В Playwright считается плохим тоном полагаться на состояние, оставшееся от предыдущего теста. Благодаря упомянутым выше Browser Contexts, каждый ваш тест должен начинаться «с чистого листа». Если тест №1 залогинился в систему, тест №2 не должен ожидать, что он уже залогинен. Он должен либо логиниться сам, либо использовать специальные механизмы сохранения состояния (Storage State), которые мы изучим позже.

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

    На этом этапе ваше рабочее окружение готово. У вас установлен Node.js, настроен проект с Playwright, скачаны браузеры и готов к работе TypeScript. В следующей главе мы перейдем к изучению самого языка, чтобы вы могли не просто копировать команды, а осознанно строить логику ваших проверок.

    2. Основы TypeScript для автоматизатора: типы данных, переменные и базовые конструкции

    Основы TypeScript для автоматизатора: типы данных, переменные и базовые конструкции

    Представьте, что вы пишете тест для интернет-магазина. Вам нужно проверить, что цена товара после применения скидки рассчитана верно. В обычном JavaScript вы могли бы случайно сложить число 100 со строкой "50", получив в итоге странный результат "10050". Тест пройдет, но логика будет сломана. TypeScript — это ваш «умный корректор», который подчеркнет ошибку красным еще до того, как вы запустите браузер. Для автоматизатора это означает экономию часов на отладке «глупых» ошибок и возможность использовать автодополнение кода на полную мощность.

    Почему автоматизаторы выбирают TypeScript

    TypeScript (TS) — это строго типизированная надстройка над JavaScript (JS). Любой валидный JS-код является валидным TS-кодом, но TS добавляет слой метаданных о типах. В контексте Playwright это дает три критических преимущества:

  • Интеллектуальное автодополнение (IntelliSense): когда вы вводите page., редактор точно знает, какие методы доступны у объекта страницы, какие аргументы они принимают и что возвращают.
  • Безопасность рефакторинга: если вы решите переименовать класс страницы в рамках паттерна Page Object, TypeScript подсветит все места в тестах, где это изменение что-то сломало.
  • Документированность кода: типы служат живой документацией. Глядя на сигнатуру функции, вы сразу понимаете, ожидает она строку, число или сложный объект конфигурации.
  • Переменные и константы: let против const

    В современном TypeScript мы практически не используем старое ключевое слово var из-за его специфической области видимости. Наш арсенал — это const и let.

    | Ключевое слово | Описание | Применение в тестах | | :--- | :--- | :--- | | const | Константа, значение нельзя изменить после инициализации. | Локаторы, URL, конфигурации, ссылки на страницы. | | let | Переменная с блочной областью видимости. | Счетчики циклов, промежуточные вычисления, буферы данных. |

    Пример использования:

    > Золотое правило автоматизатора: всегда используйте const, пока не поймете, что вам действительно нужно изменить значение переменной. Это делает код более предсказуемым.

    Базовые типы данных в контексте тестирования

    TypeScript позволяет явно указывать тип переменной после двоеточия. Это называется аннотацией типа.

    String (Строки)

    Используются для URL-адресов, селекторов, текстов кнопок и любых данных, вводимых в поля.

    typescript const price: number = 45.99; const quantity: number = 5; const totalPrice: number = price * quantity; typescript const isVisible: boolean = await page.isVisible('.header'); const isEnabled: boolean = true; typescript const menuItems: string[] = ['Home', 'Contact', 'About']; const prices: Array<number> = [10, 20, 30]; // Запись через Generic typescript interface UserData { username: string; email: string; age?: number; // Необязательное поле readonly id: number; // Только для чтения }

    const testUser: UserData = { username: 'test_user', email: 'test@example.com', id: 101 }; typescript function calculateDiscount(price: number, discount: number): number { return price - (price * discount / 100); }

    // Асинхронная функция (шаг теста) async function login(page: Page, user: UserData): Promise<void> { await page.fill('#user', user.username); await page.click('#login-btn'); } typescript const cartCount = await page.innerText('.cart-badge');

    if (parseInt(cartCount) > 0) { await page.click('.checkout'); } else { console.log('Корзина пуста'); } typescript const rows = await page.locator('tr').all();

    for (const row of rows) { const text = await row.innerText(); console.log(Текст строки: a === ba !== ba > ba \geq b$ — сравнение величин.

    Приведение типов:

  • Number(string) — из строки в число.
  • value.toString() — из числа в строку.
  • Практические советы профессора

  • Избегайте any любой ценой. Это лишает вас защиты TypeScript.
  • Используйте readonly для тестовых данных. Чтобы случайно не изменить учетные данные в ходе теста.
  • Явно указывайте возвращаемые типы. Это делает код понятнее для коллег.
  • Пользуйтесь Optional Chaining (?.). Например: user?.address?.city`. Это предотвратит падение теста, если объект не найден.
  • TypeScript — это каркас вашего будущего фреймворка. Чем точнее вы опишете типы данных сейчас, тем проще будет поддерживать сотни тестов в будущем.

    3. Работа с элементами страницы: типы локаторов и выполнение пользовательских действий

    Работа с элементами страницы: типы локаторов и выполнение пользовательских действий

    Представьте, что вы пытаетесь объяснить человеку, который никогда не видел компьютер, как купить книгу в интернет-магазине. Вы не скажете: «Нажми на пиксель с координатами 450 на 300». Вы скажете: «Найди кнопку с надписью "Купить"» или «Нажми на иконку корзины в верхнем правом углу». Playwright работает точно так же. Вместо того чтобы привязываться к хрупким техническим деталям реализации страницы, он предлагает взаимодействовать с элементами так, как это делает реальный пользователь.

    Философия локаторов в Playwright

    В автоматизации тестирования «локатор» — это способ найти элемент на странице. Если раньше стандартом индустрии считались XPath и CSS-селекторы, то Playwright смещает фокус в сторону User-facing locators (локаторов, ориентированных на пользователя).

    Почему это важно? Веб-интерфейсы постоянно меняются. Разработчик может заменить <div> на <span> или переписать стили, что мгновенно «сломает» классический CSS-селектор. Но если кнопка по-прежнему называется «Отправить», тест должен продолжать работать. Playwright поощряет использование атрибутов, которые важны для доступности (Accessibility) и видимого текста.

    Объект Locator в Playwright — это не просто ссылка на элемент, а описание того, как его найти в любой момент времени. Это критически важное отличие: локатор «ленив». Он не ищет элемент сразу при создании переменной. Он выполняет поиск непосредственно перед тем, как вы решите на него нажать или считать его текст.

    Основные типы локаторов

    Playwright предоставляет набор встроенных методов, которые покрывают 90% нужд автоматизатора. Рассмотрим их иерархию и правила применения.

    Локаторы по ролям (getByRole)

    Это самый мощный и рекомендуемый способ поиска. Он опирается на ARIA-роли (Accessible Rich Internet Applications), которые браузер и вспомогательные технологии (скринридеры) используют для понимания структуры страницы.

    Здесь button — это роль, а объект { name: 'Войти' } — уточняющий фильтр. Использование getByRole гарантирует, что ваш тест проверяет не только наличие картинки, похожей на кнопку, но и то, что эта кнопка доступна для взаимодействия.

    Локаторы по тексту и подписям

    Если у элемента нет четкой роли или вам нужно найти специфический текст, используются следующие методы:

  • getByText: Ищет элемент по видимому текстовому содержимому. Идеально для проверки сообщений об ошибках или заголовков.
  • getByLabel: Ищет поля ввода по связанному с ними тексту <label>. Это именно то, как люди заполняют формы: мы ищем глазами надпись «Имя пользователя» и пишем в поле рядом.
  • getByPlaceholder: Находит инпуты по тексту-подсказке, который исчезает при начале ввода.
  • getByAltText: Используется для изображений. Если у картинки заполнен атрибут alt, Playwright найдет её.
  • Технические локаторы: getByTestId

    Иногда текст на сайте меняется слишком часто (например, из-за локализации на разные языки), а роли элементов дублируются. В таких случаях лучшая практика — договориться с разработчиками о добавлении специальных атрибутов для тестов. По умолчанию Playwright ищет атрибут data-testid.

    Это делает тесты максимально стабильными, так как data-testid предназначен только для автоматизации и не меняется при редизайне.

    Продвинутые стратегии поиска и фильтрации

    В реальных приложениях интерфейсы сложнее, чем одна кнопка на белом фоне. Часто нам нужно найти «ту самую кнопку удаления в третьей строке таблицы». Для этого Playwright предлагает механизмы уточнения.

    Фильтрация (filter)

    Метод .filter() позволяет сузить выборку из уже найденных элементов. Представьте список товаров, где у каждого есть кнопка «В корзину».

    В этом примере мы сначала находим все карточки товаров, затем оставляем только ту, где есть текст «iPhone 15», и уже внутри этой карточки ищем кнопку. Это предотвращает нажатие на кнопку другого товара.

    Вложенность (Chaining)

    Локаторы можно объединять в цепочки. Каждое последующее звено ищет элементы только внутри результатов предыдущего.

    Работа со списками

    Если локатор находит несколько элементов, вы можете обратиться к конкретному по индексу или обработать их все.

    * first(), last() — быстрый доступ к началу или концу списка. * nth(index) — доступ по порядковому номеру (индексация с 0). * all() — возвращает массив локаторов для итерации.

    > Важно: Избегайте использования nth(index), если есть возможность зацепиться за уникальный текст или свойство. Индексы в вебе крайне нестабильны — один новый рекламный баннер может сдвинуть все элементы на одну позицию вниз, и ваш тест упадет.

    Выполнение действий: взаимодействие с интерфейсом

    Найти элемент — это только половина дела. Вторая половина — совершить действие. Playwright автоматически ждет, пока элемент станет «действующим» (Actionable). Это означает, что он должен быть:

  • Присутствующим в DOM.
  • Видимым (не скрыт через display: none или opacity: 0).
  • Стабильным (не перемещается по экрану, например, во время анимации).
  • Не перекрытым другими элементами.
  • Включенным (не имеет атрибута disabled).
  • Клик и ввод текста

    Самые частые действия — это click() и fill().

    Метод fill() предпочтительнее для простых форм, так как он работает мгновенно. pressSequentially() имитирует реальную скорость печати человека, что полезно для тестирования выпадающих списков, которые начинают поиск после третьего введенного символа.

    Работа с формами: чекбоксы, радиокнопки и селекты

    Для специальных элементов ввода в Playwright есть выделенные методы, которые учитывают их специфику.

    Чекбоксы и радиокнопки: Вместо того чтобы просто кликать по ним, используйте check() и uncheck(). Эти методы сначала проверяют текущее состояние элемента. Если вы вызовете check() на уже отмеченном чекбоксе, Playwright ничего не сделает, что гарантирует предсказуемый результат.

    Выпадающие списки (Select): Для стандартных HTML-селектов используется метод selectOption(). Он позволяет выбирать элемент по значению (value), тексту или индексу.

    Загрузка файлов и Drag-and-Drop

    Playwright упрощает работу с системными диалогами. Для загрузки файла не нужно нажимать на кнопку и пытаться взаимодействовать с окном Windows или macOS. Нужно просто «подложить» путь к файлу в элемент типа input[type="file"].

    Для перетаскивания элементов (Drag-and-Drop) существует метод dragTo():

    Нюансы использования CSS и XPath

    Хотя Playwright продвигает «человекочитаемые» локаторы, знание CSS и XPath остается обязательным навыком. Бывают ситуации, когда в коде страницы нет внятных ролей или текстов (например, сложные графики, канвасы или динамические ID).

    CSS-селекторы быстры и лаконичны. * page.locator('.submit-btn') — поиск по классу. * page.locator('#user-123') — поиск по ID. * page.locator('article >> button') — вложенность через синтаксис Playwright.

    XPath незаменим, когда нужно искать «вверх» по дереву элементов (к родителям) или когда логика поиска слишком сложна для CSS. * page.locator('//button[contains(text(), "Удалить")]/ancestor::tr') — найти строку таблицы, в которой находится кнопка удаления.

    > Помните: Playwright автоматически определяет тип селектора. Если строка начинается с // или xpath=, он будет использовать XPath. Если нет — попробует CSS.

    Обработка динамических состояний

    Современные веб-приложения живут своей жизнью: данные подгружаются, элементы исчезают. Playwright решает это через Auto-waiting, но иногда нам нужно явно управлять процессом.

    Например, метод hover() (наведение курсора) часто используется для раскрытия выпадающих меню. После наведения нам нужно дождаться, пока меню станет видимым, прежде чем кликать.

    Практические советы по выбору локаторов

    Чтобы ваши тесты не превратились в кошмар при первом же обновлении сайта, следуйте правилам «пирамиды стабильности»:

  • Приоритет №1: Роли и Текст. getByRole, getByText, getByLabel. Это делает тесты похожими на документацию.
  • Приоритет №2: Тестовые ID. getByTestId, если интерфейс слишком изменчив.
  • Приоритет №3: CSS-селекторы. Для стабильных классов и атрибутов.
  • Приоритет №4: XPath. Только в крайних случаях для сложной навигации по DOM.
  • Избегайте «длинных путей» вроде body > div > div:nth-child(2) > span > a. Любое изменение в обертке (например, добавление рекламного контейнера) сломает этот путь.

    Разбор примера: Автоматизация формы регистрации

    Давайте соберем все знания воедино и напишем сценарий взаимодействия с формой. Представим страницу регистрации с полями: Имя, Email, Чекбокс «Согласие» и кнопка «Создать аккаунт».

    В этом примере мы не использовали ни одного CSS-класса. Если разработчики изменят дизайн, поменяют цвета или перенесут блоки местами, тест останется зеленым, пока функциональность (текст и роли) сохраняется.

    Граничные случаи и частые ошибки

    Ошибка 1: Попытка кликнуть по скрытому элементу. Если элемент находится за пределами видимости, Playwright попытается его проскроллить. Но если он перекрыт модальным окном или «липким» хедером, клик может не пройти. В таких случаях можно использовать click({ force: true }), но это плохая практика, так как реальный пользователь не может нажать на перекрытый элемент. Лучше сначала закрыть мешающее окно.

    Ошибка 2: Использование локаторов, которые находят много элементов. Если вы напишете page.getByRole('button').click(), а на странице 10 кнопок, Playwright выдаст ошибку strict mode violation. Это защитный механизм. Он заставляет вас быть точнее: либо уточнить имя кнопки, либо использовать фильтрацию.

    Ошибка 3: Ожидание через page.waitForTimeout(). Никогда не используйте «сон» (паузу на фиксированное количество секунд). Это делает тесты медленными и нестабильными. Playwright сам ждет элементы. Если автоожидания не хватает, используйте locator.waitFor(), который сработает сразу, как только условие выполнится.

    Замыкание темы

    Мастерство работы с локаторами — это баланс между надежностью и читаемостью. Используя методы getByRole, getByLabel и getByText, вы создаете тесты, которые не просто проверяют код, а имитируют поведение человека. Это делает вашу автоматизацию устойчивой к изменениям верстки и полезной для бизнеса, так как тесты начинают говорить на языке интерфейса, а не на языке тегов и атрибутов. В следующей главе мы разберем, как Playwright управляет временем и почему вам больше никогда не придется писать sleep(5000).