Как грамотно организовать тесты в Playwright

от автора

При работе со сквозным тестированием (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, но не знаете, с чего начать? Или, возможно, вам нужно освоить новые инструменты, чтобы улучшить процесс тестирования в вашем проекте? В любом случае рекомндуем обратить внимание на открытые уроки:

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


ссылка на оригинал статьи https://habr.com/ru/articles/927572/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *