При работе со сквозным тестированием (E2E, end-to-end) в Playwright критическое значение имеет поддержание упорядоченной и масштабируемой тестовой базы. Хорошо организованная структура не только улучшает поддерживаемость, но и облегчает адаптацию новых коллег. В этой статье мы рассмотрим, как организовать тесты в Playwright наилучшим образом, начиная со структуры папок и заканчивая использованием хуков, аннотаций и тегов.
Структурирование папок с тестами
Тесты в Playwright обычно хранятся в папке tests. В этой папке можно создавать несколько уровней подпапок для лучшей организации тестов. Например, при работе с тестами, которые требуют аутентификации пользователей, разделение тестов на авторизованного и неавторизованного пользователя делает тестовую базу более чистой. Пример структуры папок, которую можно использовать:
/tests /helpers - list-test.ts # кастомная фикстура для страницы с списком фильмов - list-utilities.ts # функции хелперы для создания списков фильмов /logged-in - api.spec.ts # API тесты для пользователей, вошедших в систему - login.setup.ts # Тесты для входа в систему - manage-lists.spec.ts # Тесты для управления списками фильмов /logged-out - api.spec.ts # Тесты API для пользователей, не вошедших в систему - auth.spec.ts # Тесты потока аутентификации - movie-search.spec.ts # Тесты для поиска фильмов - sort-by.spec.ts # Тесты для сортировки фильмов
Тестовые хуки в Playwright
В Playwright есть тестовые хуки, такие как beforeEach и afterEach, для выполнения общих задач настройки и очистки перед и после каждого теста. Эти хуки особенно полезны для таких действий, как вход в систему, подготовка тестовых данных или навигация на нужную страницу перед каждым тестом.
test.beforeEach(async ({ page }) => { await page.goto(''); }); test('должен отредактировать существующий список', async ({ page }) => { // ... }); test('должен добавлять и удалять фильмы из списка', async ({ page }) => { // ... });
Когда подготовка и очистка выполняются для нескольких тестов, функции хелперы (или вспомогательные функции) помогут избежать дублирования кода и поддержать принцип DRY . Ниже приведен пример вспомогательных функций для создания списка фильмов:
import { test, expect, Page } from '@playwright/test'; export async function createList( page: Page, listName: string, listDescription: string, ) { await test.step('создать новый список', async () => { await page.getByLabel('Профиль пользователя').click(); await page.getByRole('link', { name: 'Создать новый список' }).click(); await page.getByLabel('Имя').fill(listName); await page.getByLabel('Описание').fill(listDescription); await page.getByRole('button', { name: 'Продолжить' }).click(); }); } export async function openLists(page: Page, name: string = 'Мои списки') { //... }
Функции хелперы могут быть использованы в хуке beforeEach в различных тестовых файлах, чтобы каждый тест начинался с уже созданного списка фильмов и открытой страницы с списками:
import { test, expect } from '@playwright/test'; import { addMovie, createList, openLists } from '../helpers/list-utilities'; // Перед каждым тестом переходим на базовый URL, создаем список и открываем страницу со списками test.beforeEach(async ({ page }) => { await page.goto(''); await createList( page, 'мои любимые фильмы', 'вот список моих любимых фильмов', ); await openLists(page); }); test('должен отредактировать существующий список', async ({ page }) => { await page.getByRole('link', { name: 'мои любимые фильмы' }).click(); await page.getByRole('link', { name: 'Редактировать' }).click(); // ... }); test('должен добавлять и удалять фильмы из списка', async ({ page }) => { await page.getByRole('link', { name: 'мои любимые фильмы' }).click(); await page.getByRole('button', { name: 'Добавить/Удалить фильмы' }).click(); //... });
Фикстуры
Фикстуры могут быть использованы вместо хука beforeEach и являются отличным способом создания контекста страницы, который можно использовать в нескольких тестах. Фикстуры можно определить в отдельном файле и импортировать в тестовые файлы, где они необходимы. Пример кастомной фикстуры для страницы с фильмами:
export const listTest = baseTest.extend<{ listPage: Page }>({ listPage: async ({ context }, use) => { // настройка фикстуры const page = await context.newPage(); await page.goto(''); await createList(page, 'мои любимые фильмы', 'список моих любимых фильмов'); await listTest.step('добавить фильмы в список', async () => { await addMovie(page, 'Twisters'); await addMovie(page, 'The Garfield Movie'); await addMovie(page, 'Bad Boys: Ride or Die'); }); //... });
Фикстура может использоваться в тестах, импортируя ее и передавая как аргумент в функцию test, вместо использования встроенной фикстуры page Playwright. Каждый тест, использующий кастомную фикстуру, начнётся с уже подготовленной страницы, на которой есть список фильмов:
import { expect } from '@playwright/test'; import { listTest as test } from '../helpers/list-test'; import { addMovie } from '../helpers/list-utilities'; test('редактирование существующего списка', async ({ listPage }) => { // Используем страницу из фикстуры listPage const page = listPage; await page.getByRole('link', { name: 'Редактировать' }).click(); // ... });
Разбиение тестов на шаги с помощью test.step
Если вы хотите сделать тесты более понятными, полезной окажется функция test.step в Playwright. Она разбивает сложные тесты на более понятные короткие шаги, что повышает читаемость и улучшает отчётность.
import { test, expect } from '@playwright/test'; test('должен добавлять и удалять фильмы из списка', async ({ page }) => { const movieList = page.getByRole('listitem', { name: 'movie' }); await page.getByRole('link', { name: 'мои любимые фильмы' }).click(); await page.getByRole('button', { name: 'Добавить/Удалить фильмы' }).click(); await test.step('добавить фильмы в список и проверить их', async () => { await addMovie(page, 'Twisters'); await addMovie(page, 'Bad Boys: Ride or Die'); await expect .soft(movieList) .toHaveText([/Twisters/, /Bad Boys: Ride or Die/]); }); await test.step('удалить фильмы из списка и проверить изменения', async () => { const movie1 = page.getByRole('listitem').filter({ hasText: 'Twisters' }); await movie1.getByLabel('Удалить').click(); await expect.soft(movieList).toHaveText([/Bad Boys: Ride or Die/]); }); });
Использование встроенных аннотаций: skip, fail и fixme
Аннотации в Playwright помогают маркировать тесты в зависимости от их поведения или условий выполнения, например, пропускать тесты в зависимости от определённых условий, помечать как ожидаемо неудачные или помечать флагом как требующие внимания. Давайте рассмотрим каждую из них с примерами:
1. test.skip: Условный пропуск тестов
Аннотация test.skip полезна, когда необходимо пропустить тест в зависимости от определённых условий или конфигурации. Например, вы можете захотеть пропустить тесты для конкретных браузеров, в определённых окружениях или когда недоступна какая-либо функция.
import { test, expect } from '@playwright/test'; test('гамбургер-меню на мобильных устройствах', async ({ page, isMobile }) => { // Пропустить тест на мобильных устройствах test.skip(!isMobile, 'Тест актуален только для десктопа'); await page.goto('/'); //.. }); test('не должно работать на Safari', async ({ page, browserName }) => { // Пропустить тест на Safari из-за известных проблем с совместимостью test.skip(browserName === 'webkit', 'Safari не поддерживает эту функцию'); await page.goto(''); //.. });
2. test.fixme: Пометка тестов для исправления
Используйте test.fixme для пометки тестов, которые нужно исправить позже. Эта аннотация используется для пометки неполных или неправильно реализованных тестов. Playwright автоматически пропустит такие тесты и отразит их в отчётах, что послужит напоминанием о необходимости их доработки.
import { test, expect } from '@playwright/test'; // Помечаем этот тест как "fixme", так как он еще не полностью реализован test.fixme('войти в систему и проверить доступ к профилю', async ({ page }) => { await page.goto(''); await page.getByRole('banner').getByLabel('Войти').click(); await page .getByPlaceholder('you@example.com') .fill(process.env.MOVIES_USERNAME!); await page.getByPlaceholder('Пароль').fill(process.env.MOVIES_PASSWORD!); await page.getByRole('button', { name: 'Войти' }).click(); await page.getByLabel('Профиль пользователя').click(); });
Как эти аннотации упрощают тестирование
-
test.skip — удобный способ условного пропуска тестов в зависимости от критериев, таких как окружение, платформа или доступность функции. Это помогает поддерживать «зелёный» тестовый набор, пропуская нерелевантные тесты, а не позволяя им падать.
-
test.fixme полезен для пометки незавершённых или не реализованных тестов. Эти тесты пропускаются автоматически и помечаются в отчётах, напоминая о необходимости их доработки в будущем.
Резюме использования аннотаций
Применение этих аннотаций поможет упростить ваш рабочий процесс, снизить количество ложных срабатываний в тестах и четко донести до вашей команды информацию об известных проблемах и незавершённых тестах.
Добавление пользовательских аннотаций
В Playwright вы можете добавлять к своим тестам кастомные аннотации. Например, довольно распространённой практикой является добавление ссылки на связанную проблему. Это полезно для отчётов и будет отображаться в интерфейсе. Вот как добавить ссылку на проблему в ваши тесты:
test( 'должен удалить список', { annotation: { type: 'issue', description: 'https://github.com/microsoft/demo.playwright.dev/issues/58', }, }, async ({ page }) => { await page.getByRole('link', { name: 'мои любимые фильмы' }).click(); await page.getByRole('link', { name: 'Редактировать' }).click(); await page.getByRole('link', { name: 'Удалить список' }).click(); // ... оставшиеся шаги теста });
Использование тегов для фильтрации и организации тестов
Теги — мощный инструмент для организации и фильтрации тестов. Вы можете использовать теги для организации тестов по функциям, приоритетам, ролям пользователей или циклам выпуска. Это позволяет легко фильтровать и запускать нужные тесты или генерировать целевые отчёты.
Как добавлять теги к тестам
В Playwright вы можете добавлять теги как часть метаданных теста. Вот пример того, как можно определить теги для тестов:
test('сортировка с мокированием API', { tag: '@mocking' }, async ({ page }) => { // Мокируем вызов API для сортировки по популярности await page.route('*/**/**sort_by=popularity.desc', async (route) => { await route.fulfill({ path: path.join(__dirname, '../mocks/sort-by-popularity.json'), }); }); });
В этом примере мы пометили тест тегом @mocking. Эта метаинформация будет использоваться для фильтрации тестов в отчётах или при выполнении командной строки.
Запуск тестов с фильтрацией по тегам
Чтобы запустить тесты с конкретными тегами, можно использовать флаг --grep с указанием имени тега:
npx playwright test --grep @mocking
Чтобы исключить тесты с конкретным тегом, используйте флаг --grep-invert:
npx playwright test --grep-invert @mocking
Фильтрация по тегам в HTML-отчётах
Теги отображаются в HTML-отчёте, что облегчает идентификацию и фильтрацию тестов по тегам при просмотре результатов. Это может быть очень полезно для отладки или фокусировки на подмножестве тестов, связанных с определённой функцией.
Резюме
Следуя этим рекомендациям, вы сможете создать хорошо структурированный и поддерживаемый тестовый набор для Playwright:
-
Организованная структура папок. Разделяйте тесты по их контексту (вошёл / не вошёл в систему) и по функциональности. Например, при тестировании GitHub у нас могут быть папки tests/repos, tests/prs, tests/issues и так далее.
-
Использование хуков и блоков Describe. Улучшайте читаемость и создавайте общие предварительные условия.
-
Определение шагов. Используйте
test.step, чтобы разбить сложные тест-кейсы на более понятные шаги. -
Использование аннотаций и тегов. Помечайте тесты с ошибками или незавершённые тесты, добавляйте ссылки на проблемы и категоризируйте тесты для лучшей фильтрации и отчётности.
С продуманным подходом к организации тестов вы сможете создать более чистую и поддерживаемую тестовую базу, которая будет хорошо масштабироваться с вашим приложением.
Может быть, вы давно задумываетесь о переходе в QA, но не знаете, с чего начать? Или, возможно, вам нужно освоить новые инструменты, чтобы улучшить процесс тестирования в вашем проекте? В любом случае рекомндуем обратить внимание на открытые уроки:
-
15 июля в 20:00 — Вы уже тестировщик. Просто не знали об этом
Как превратить ежедневные навыки в востребованную IT-профессию. -
23 июля в 20:00 — Тестирование React-приложений с помощью React Testing Library
Как писать надежные тесты для компонентов React без лишних деталей реализации. -
19 августа в 19:00 — Docker Compose для тестировщика: легко о сложном
Настройка тестовых сред с помощью Docker Compose и ускорение процесса автоматизации.
Если у вас уже есть опыт в тестировании и вы хотите двигаться дальше к управлению QA — пройдите вступительный тест, чтобы оценить свой уровень и узнать, подойдет ли вам программа курса «QA Lead».
ссылка на оригинал статьи https://habr.com/ru/articles/927572/
Добавить комментарий