End-to-end тестирование React приложения с помощью Playwright
Мы с Dalle-3 визуализировали работу над задачей
Привет, я Лиза — веб разработчик в одной зарубежной компании. Хочу поделиться тем, как я автоматизировала регрессионное тестирование в рабочем проекте на React с использованием довольно нового фреймворка Playwright. Разберемся, почему именно этот фреймворк, какие подводные камни, как обойти авторизацию и кто этим пользуется.
Зачем нужны end-to-end тесты
End-to-end (e2e) тестирование — это способ убедиться, что каждый шаг, который пользователь делает, и все изменения данных проходят без проблем. Оно не заменяет другие виды тестирования, а, наоборот, дополняет их, обеспечивая комплексную проверку функциональности, производительности и стабильности всего приложения.
В нашем проекте изначально использовались только юнит тесты и то, не в активном режиме и необязательные. QA тестировщика тоже не было, а потребность в тестировании всего приложения была и хотелось автоматизировать важные базовые флоу для регрессионного тестирования.
Почему Playwright
Playwright — это фреймворк с открытым исходным кодом для автоматизации тестирования конечного пользователя. Он поддерживает большинство современных браузеров, включая Firefox, Chromium и Webkit с использованием единого API. Playwright создан и поддерживается компанией Microsoft и постепенно завоевывает популярность.
Также удобно, что Playwright поддерживает Jest, Mocha, Jasmine и другие известные серверы непрерывной интеграции и предоставляет поддержку различных языков программирования, включая TypeScript, JavaScript, Python, .NET и Java.
Сравнение с другими фреймворками
Я сравнивала этот фреймворк с другими фреймворками для тестирования, такими как Puppeteer, Cypress и WebDriverIO. Именно они были выбраны в качестве кандидатов из-за их широкой популярности как на рынке, так и в моей компании.
Поддержка браузеров выбранными для анализа фреймворками
Как можно заметить, Puppeteer не поддерживает тестирование в Safari, что было критичном фактором для выбора фреймворка в нашем проекте. Cypress использует Mocha.js, а также не является оптимальным вариантом, поскольку не поддерживает тестирование end-to-end для iOS. Кроме того, экспериментальная поддержка Safari в Cypress была бы недостаточной из-за отсутствия некоторых функций и известных ошибок (могут быть затронуты захват событий и навигация по сайту).
В сравнении WebdriverIO и Playwright решающими факторами стали скорость, поддержка записи видео и подержанные языки приложения.
Npm тренды скачивания Playwright vs WebdriverIO
Кроме того, анализируя тенденции установки через Npm, видно, что количество установок Playwright недавно превысило количество установок WebdriverIO. Эта тенденция может говорить о том, что Playwright, скорее всего, станет будущим лидером среди фреймворков для многобраузерного e2e тестирования веб-приложений, что в свою очередь приведет к увеличению числа разработчиков и комьюнити.
Дополнительным решающим фактором было то, что у нас в проекте уже были написаны unit тесты на Jest до этого, а у Playwright есть beta поддержка компонентного тестирования. С его использованием появилась бы возможность перевести unit тесты на тот же фреймворк и дебажить в настоящем браузере с брейкпоинтами вместо виртуального DOM-дерева в случае с Jest.
Подготовка проекта
Приняли решение использовать Playwright для e2e и потенциально компонентного тестирования, что дальше?
Настройка для end-to-end тестирования
Для полноценного тестирования нужно установить библиотеку playwright как в документации. Мы используем yarn
yarn create playwright
Что будет скачано:
playwright.config.ts
package.json
package-lock.json
tests/
example.spec.ts
tests-examples/
demo-todo-app.spec.ts
Одной из важных деталей здесь является playwright.config.ts
. В этом файле можно конфигурировать запуск тестов непосредственно под ваш проект и нужды.
Например, настроить браузеры (в нашем случае только Chrome):
projects: [
{
name: 'chromium',
use: { ...devices['Desktop Chrome'] },
},
],
Настроить конкретный URL, если нужно ходить не локально в проект:
use: {
trace: 'on-first-retry',
baseURL: process.env.PLAYWRIGHT_URL ?? 'http://localhost:1234',
},
Выставить таймаут, который будет выполняться перед каждой проверкой в тестах:
expect: {
timeout: 5000,
},
Настройка для компонентного тестирования (beta)
Описана в отдельном разделе документации.
Для установки нужно выполнить следующие команды:
yarn create playwright --ct
yarn add @playwright/experimental-ct-react
Здесь я обнаружила первую проблему: компонентное тестирование предполагает, что в проекте установлен React 18 (баг). В нашем версия 17, поэтому устанавливать нужно
yarn add @playwright/experimental-ct-react17
Файл конфигурации для компонентного тестирования лучше завести отдельный и настроить там другой путь для юнит тестов, чтобы не путать с end-to-end.
Написание тестов
Далее, если всё пошло так, можно начать писать тесты.
Пример полноценного dummy теста:
import { test, expect } from '@playwright/test';
test('get started link', async ({ page }) => {
await page.goto('https://playwright.dev/');
await page.getByRole('link', { name: 'Get started' }).click();
await expect(page.getByRole('heading', { name: 'Installation' })).toBeVisible();
});
Запускаем
npx playwright test --ui
С параметром --ui
тесты откроются в отдельном интерфейсном окне. В нем помимо запуска тестов, можно останавливать их в любом месте, специальным locator picker«ом выбирать любой элемент страницы, смотреть выполнение теста по шагам в удобном таймлайне. Я не работала в таких режимах с другими тестами, так что мне просто очень нравится этот. Пример интерфейса беру из документации в целях сохранения приватности нашего проекта.
Пример интерфейса для запуска тестов на Playwright
Обработка проблем
Что после этого может пойти не так? Рассмотрим несколько проблем, с которыми мне пришлось столкнуться. Имеющийся легаси код повлек за собой: невозможность использования .js файлов, с имеющимся в них JSX кодом, а также файлов и компонент, в которых есть дефолтный экспорт.
Первую проблему с .js разрешением файлов можно решить, добавив настройку в конфиг:
/* Vite config */
ctViteConfig: {
optimizeDeps: {
force: true,
esbuildOptions: {
loader: {
'.js': 'jsx',
},
},
},
},
Подобные настройки подходят для проектов, которые используют Vite сервер. Внутрь ctViteConfig
можно добавлять и другие конструкции, которые могут помочь с компонентным тестированием. Я пробовала настроить его для второй проблемы с дефолтными экспортами, но пока что единственным решением стало механическое изменение каждого дефолтного экспорта на именованный.
Двойная Google аутентификация
Второй более серьезной проблемой стала двойная аутентификация, которая есть у нас в проекте и нужна была для открытия приложения в тестах. Двойная аутентификация подразумевает, что после ввода данных в Гугл форму, нужно затем вторым способом подтвердить свою личность, в нашем случае с телефона. А это в свою очередь значит, что полностью автоматизировать тесты (интегрировать их в CI/CD) таким образом будет невозможно.
Возможные обходные решения:
делать моки запросы с бэкенда, чтобы не требовалось аутентификации для их выполнения (но тогда это нечестный end-to-end);
создать тестового пользователя и отключить у него двойную аутентификацию (это оказалось сложно из-за специфики проекта);
попытаться сохранить токен авторизации конкретного пользователя в локальный .env файл и не коммитить его в репозиторий (тут нарушается приватность конкретного живого пользователя с его данными);
создать отдельное окружение на бэкенде конкретно под тесты с облегченными запросами (может быть сложно и времязатратно).
В нашем случае оказалось, что кто-то в проекте ранее уже сделал обходной путь с созданием временного пользователя с необходимыми для запросов данными, под которым можно заходить без авторизации. Так появилась надежда, что запуск тестов можно внедрять в CI на Github.
Интеграция с CI/CD
Данный этап пока в процессе реализации из-за специфики проекта и вопроса необходимости запуска всех тестов на каждом пулл реквесте. Преимущества в такой интеграции для задач средней и высокой сложности точно есть: регрессионные тесты будут проходить все базовые флоу и снизится количество незамеченных ошибок, багов в продакшн коде и инцидентов.
Возможности внедрения тоже существуют, например, запускать тест кейсы на уже собранном в CI стенде с кодом ветки конкретного пулл реквеста. Но пока больше информации можно найти здесь. Мы на данном этапе запускаем тесты локально при добавлении нового функционала, и это действительно влияет в лучшую сторону на проект, к тому же помогает нам самим лучше ориентироваться в логике и добавлять больше покрытия.
Помимо этого, можно также переписывать существующие на Jest юнит тесты на Playwright, чтобы иметь возможность визуально смотреть на отдельные компоненты и дебажить настоящее DOM-дерево, вместо виртуального.
Полезные советы и рекомендации
Для меня это был первый опыт внедрения фреймворка для тестирования в проект с нуля. С помощью большого количества ресерча, гугления, общения с людьми из команды и компании в целом, я смогла прийти к примерному пониманию куда двигаться.
Уверена, что для каждого проекта свой подход, свои технологии, так что думаю изначально можно опираться на следующие вещи:
совместимость с вашим технологическим стеком
поддержка браузеров и платформ
скорость выполнения тестов
сообщество и поддержка
Надеюсь, мой опыт вдохновит других разработчиков рассмотреть Playwright как фреймворк для тестирования. В конце концов, наша цель как разработчиков — создавать приложения, которыми легко и приятно пользоваться, а качественное тестирование — это один из ключей к достижению этой цели.