Сквозное тестирование c Playwright

Сквозное тестирование c Playwright

В этом руководстве вы изучите возможности Playwright, проведете сквозное (end-to-end) тестирование на React-версии известного проекта TodoMVC.

Этот проект служит эталоном для сравнения реализации различных JavaScript-фреймворков на одном приложении. Не волнуйтесь, если вы не знакомы с React — основное внимание уделяется тестированию с помощью Playwright, а не особенностям React.

Подпишитесь на наш ТЕЛЕГРАМ КАНАЛ ПО АВТОМАТИЗАЦИИ ТЕСТИРОВАНИЯ

Содержание:

Прежде чем продолжить, убедитесь, что у вас установлена последняя версия Node.js, предпочтительно версия LTS.

Примечание редакции: если вы еще не очень хорошо знакомы с Playwright, то возможно вам будет интересна статья Сквозное тестирование с Playwright: полное руководство

Шаг 1 — Настройка React-демо проекта

Начните с клонирования репозитория TodoMVC React на ваш локальный компьютер:

git clone https://github.com/betterstack-community/react-todo-mvc

После клонирования перейдите в директорию проекта и установите необходимые зависимости:

cd react-todo-mvc
npm install

Этот шаг гарантирует, что все необходимые библиотеки и инструменты будут доступны для сервера разработки. После установки вы можете запустить сервер с помощью команды:

npm run dev

Сервер инициализируется и начнет прослушивать порт 8080. Вывод будет похож на:

> todomvc-react@1.0.0 dev
> webpack serve --open --config webpack.dev.js

<i> [webpack-dev-server] Проект запущен на:
<i> [webpack-dev-server] Loopback: http://localhost:8080/
<i> [webpack-dev-server] В вашей сети (IPv4): http://192.168.0.189:8080/
. . .

Чтобы убедиться, что приложение работает правильно, откройте в браузере http://localhost:8080. Вы увидите интерфейс TodoMVC. Попробуйте добавить несколько задач, чтобы убедиться, что приложение функционирует.

Теперь с помощью Playwright вы создадите тесты, которые проверят основные функции приложения, такие как возможность добавлять и управлять задачами. Эти тесты продемонстрируют мощь и простоту Playwright для автоматизированного тестирования браузера.

Перед тем как перейти к следующему шагу, остановите сервер разработки. Это можно сделать, нажав Ctrl-C в терминале, где запущен сервер. Сервер завершит работу корректно:

^C [webpack-dev-server] Gracefully shutting down. To force exit, press ^C again. Please wait...

Теперь, когда демо-проект настроен, можно интегрировать и настроить Playwright для написания и запуска сквозных тестов.

Шаг 2 — Настройка Playwright

В этом разделе вы установите Playwright в проект и настроите браузерные движки, необходимые для сквозного тестирования.

Начните с добавления Playwright в ваш проект. В корневой директории проекта выполните следующую команду:

npm init playwright@latest

Во время установки вам предложат настроить несколько параметров. Для нашего проекта выберите следующие параметры:

Initializing project in 'react-todo-mvc'
✔ Do you want to use TypeScript or JavaScript? · JavaScript
✔ Where to put your end-to-end tests? · tests
✔ Add a GitHub Actions workflow? (y/N) · false
✔ Install Playwright browsers (can be done manually via 'npx playwright install')? (Y/n) · true
✔ Install Playwright operating system dependencies (requires sudo / root - can be done manually via 'sudo npx playwright install-deps')? (y/N) · true

После установки вы увидите сообщение о завершении, показывающее, что Playwright и его зависимости теперь являются частью вашего проекта:

. . .

Рекомендуем начать с команды:

npx playwright test

И ознакомьтесь со следующими файлами:
  - ./tests/example.spec.js - Пример сквозного теста
  - ./tests-examples/demo-todo-app.spec.js - Сквозные тесты для Todo App
  - ./playwright.config.js - Конфигурация тестов Playwright

Теперь давайте настроим Playwright для нашего тестирования. Откройте файл playwright.config.js, который был создан во время установки, в вашем текстовом редакторе:

code playwright.config.js

Вот как выглядит playwright.config.js:

// @ts-check
const { defineConfig, devices } = require('@playwright/test');

module.exports = defineConfig({
  testDir: './tests',
  fullyParallel: true,
  forbidOnly: !!process.env.CI,
  retries: process.env.CI ? 2 : 0,
  workers: process.env.CI ? 1 : undefined,
  reporter: 'html',
  use: {
    baseURL: 'http://127.0.0.1:8081',
    trace: 'on-first-retry',
  },
  projects: [
    {
      name: 'chromium',
      use: { ...devices['Desktop Chrome'] },
    },
    {
      name: 'firefox',
      use: { ...devices['Desktop Firefox'] },
    },
    {
      name: 'webkit',
      use: { ...devices['Desktop Safari'] },
    },
  ],
  webServer: {
    command: 'npm run playwright-server',
    url: 'http://127.0.0.1:8081',
    reuseExistingServer: !process.env.CI,
  },
});

Playwright предлагает множество параметров настройки тестов, но наиболее важные перечислены ниже:

  • testDir: Указывает на директорию ./tests, где будут находиться ваши тестовые файлы.
  • projects: Определяет браузерные среды для тестирования (Chromium, Firefox, WebKit).
  • webServer: Позволяет запускать локальный сервер перед тестированием, что полезно в разработке.
  • use.baseURL: Задает корневой URL вашего сервера, чтобы в тестах можно было использовать относительные пути вместо абсолютных.

Прежде чем продолжить, создайте скрипт для Playwright в вашем файле package.json следующим образом:

"scripts": {
    "playwright-server": "webpack serve --port=8081 --config webpack.dev.js",
},

Этот скрипт запустит сервер разработки на другом порту специально для тестирования Playwright.

Теперь Playwright настроен и готов к написанию первого тестового скрипта.

Шаг 3 — Написание первого теста

Playwright уже создал директорию tests с примером теста. Для начала удалите этот пример:

rm tests/example.spec.js

Теперь создайте новый файл теста специально для вашего приложения To-do:

code tests/todo.spec.js

В этом новом файле теста вы напишете тест, который проверит начальное состояние приложения. Цель заключается в том, чтобы убедиться, что после загрузки нет ни одного элемента списка задач, а поле ввода находится в фокусе.

Напишите код для проверки этих условий:

const { test, expect } = require('@playwright/test');

test.describe('Initial state', () => {
  test('should be empty with focused input', async ({ page }) => {
    // Загрузка приложения TodoMVC
    await page.goto('/');

    const todoList = page.getByTestId('todo-list');

    // Убедитесь, что список не содержит элементов
    await expect(todoList).toBeEmpty();

    const todoInput = page.getByTestId('text-input');

    // Убедитесь, что поле ввода находится в фокусе
    await expect(todoInput).toBeFocused();
  });
});

Функции test и expect Playwright помогают определить тест и выполнить проверки. Метод describe()группирует связанные тесты и описывает, что охватывает данный набор тестов.

Внутри test.describe(), функция test() определяет конкретный тест для проверки пустого состояния списка задач и фокуса на поле ввода. Тест переходит на приложение TodoMVC по адресу http://localhost:8081, а затем использует локатор getByTestId() для поиска элементов по атрибуту data-testid.

Затем функция expect() используется для проверки того, что список задач пуст, а поле ввода находится в фокусе.

Чтобы запустить тест, выполните следующую команду в терминале:

npx playwright test

Эта команда запускает сервер разработки и выполняет тесты в разных браузерах, как указано в playwright.config.js. Все тесты должны пройти, что означает, что начальное состояние приложения работает как ожидалось во всех основных браузерах.

Output
. . .

Running 3 tests using 3 workers
  3 passed (4.9s)

Чтобы открыть последний HTML отчет, выполните:

npx playwright show-report

После подтверждения начального состояния приложения в следующем разделе вы протестируете более сложные взаимодействия с пользователем. Также вы изучите, как режим UI Playwright поможет понять и отладить эти взаимодействия.

Шаг 4 — Изучение UI-режима Playwright

В этой части вы создадите тест, чтобы убедиться, что задачи можно успешно добавлять в приложение, и воспользуетесь UI-режимом Playwright для визуализации и отладки выполнения теста.

Сначала обновите файл todo.spec.js, добавив новый тест:

. . .

const TODO_ITEMS = ['save the world', 'go back in time', 'learn C'];

test.describe('New Todo', () => {
  test('should allow me to add todo items', async ({ page }) => {
    await page.goto('/');

    // создаем локатор для нового списка задач
    const todoList = page.getByTestId('todo-list');
    const todoInput = page.getByTestId('text-input');

    // Добавляем первую задачу
    await todoInput.fill(TODO_ITEMS[0]);
    await todoInput.press('Enter');

    // Убедитесь, что в списке только одна задача
    await expect(page.getByTestId('todo-item-label')).toHaveText([
      TODO_ITEMS[0],
    ]);

    // Добавляем вторую задачу
    await todoInput.fill(TODO_ITEMS[1]);
    await todoInput.press('Enter');

    // Убедитесь, что в списке две задачи
    await expect(page.getByTestId('todo-item-label')).toHaveText([
      TODO_ITEMS[0],
      TODO_ITEMS[1],
    ]);
  });
});

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

Он начинается с загрузки приложения и выбора поля ввода для новых задач, используя его data-testid, а затем выполняется поэтапно:

  1. Первый элемент из массива TODO_ITEMS вводится в поле ввода, и симулируется нажатие клавиши Enter.
  2. Затем проверяется, что в списке задач содержится только этот первый элемент.
  3. Аналогично вводится второй элемент из TODO_ITEMS.
  4. Снова проверяется список задач, чтобы убедиться, что теперь в нем содержатся как первый, так и второй элементы.

Чтобы наблюдать за выполнением теста, используйте команду:

npx playwright test -g 'New Todo' --ui

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

Когда UI-режим активирован, тест сначала будет на паузе. Чтобы продолжить выполнение, нажмите на значок Play рядом с заголовком теста. Тест должен успешно выполниться без ошибок.

На временной шкале в верхней части интерфейса вы можете увидеть процесс выполнения теста. При наведении курсора на любой участок шкалы появляется снимок экрана теста. Вы также можете выбрать интервал, чтобы фильтровать действия и логи только для этой части теста.

Вкладка Actions перечисляет все действия, выполненные в тесте, с указанием использованных локаторов и продолжительности выполнения. Вы можете щелкнуть по любому действию, чтобы увидеть изменения в приложении. Вкладки Before и After позволяют визуально сравнивать состояние приложения до и после выполнения действия.

Кроме того, можно исследовать DOM на любом этапе теста, нажав на значок внешней ссылки в верхнем правом углу снимка DOM. Откроется окно, в котором вы можете использовать DevTools браузера для более детального изучения и устранения проблем в скриптах.

Под снимком DOM доступны несколько вкладок с дополнительной информацией:

  • Locator: Позволяет выбрать локаторы из снимка DOM и скопировать их в тестовый скрипт.
  • Source: Показывает код для выделенного действия.
  • Call: Отображает информацию о времени выполнения и деталях локатора.
  • Log: Содержит внутренние логи Playwright.
  • Errors: Показывает любые ошибки, возникшие во время теста.
  • Console и Network: Отображают логи приложения и сетевые запросы.
  • Attachments: Полезны для визуальных сравнений при регрессионном тестировании.

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

Шаг 5 — Обнаружение визуальных регрессий с помощью Playwright

Тестирование визуальных регрессий — это процесс проверки пользовательского интерфейса (UI) приложения на предмет визуальных изменений, которые могли возникнуть после внесения изменений в код. Оно сравнивает текущий внешний вид элементов или страниц приложения с набором базовых изображений, созданных ранее, чтобы убедиться, что элементы интерфейса выглядят правильно в разных окружениях, браузерах или после изменений кода.

Playwright значительно упрощает проверку визуальных регрессий, следуя общему процессу:

  1. Сначала создается набор базовых изображений, представляющих ожидаемое состояние элементов интерфейса или страниц. Эти изображения служат отправной точкой для будущих сравнений.
  2. Затем во время выполнения теста захватывается текущее состояние интерфейса.
  3. Далее эти изображения сравниваются с эталоном. Любые расхождения отмечаются как возможные регрессии, которые могут быть вызваны изменениями в CSS, макете, обновлениями JavaScript или поведением браузера.

Playwright использует библиотеку pixelmatch для сравнения изображений на уровне пикселей. При первом выполнении теста визуальной регрессии создается и сохраняется эталонный снимок, который служит базовой точкой для последующих сравнений.

Чтобы увидеть это на практике, добавьте следующий тест в файл todo.spec.js:

. . .

test.describe('Visual comparison', () => {
  test('initial state', async ({ page }) => {
    await expect(page).toHaveScreenshot();
  });
});

Этот тест использует метод toHaveScreenshot(), чтобы захватить и сравнить текущее состояние страницы с ожидаемым базовым изображением.

Перед выполнением теста рекомендуется провести рефакторинг кода:

const { test, expect } = require('@playwright/test');

test.beforeEach(async ({ page }) => {
  await page.goto('/');
});

test.describe('Initial state', () => {
  test('should be empty with focused input', async ({ page }) => {
    const todoList = page.getByTestId('todo-list');
    // дополнительные проверки
  });
});

const TODO_ITEMS = ['save the world', 'go back in time', 'learn C'];

test.describe('New Todo', () => {
  test('should allow me to add todo items', async ({ page }) => {
    const todoList = page.getByTestId('todo-list');
    // дополнительные проверки
  });
});

test.describe('Visual comparison', () => {
  test('initial state', async ({ page }) => {
    await expect(page).toHaveScreenshot();
  });
});

Чтобы избежать повторения строки, которая переходит на корневой путь в каждом тесте, хук beforeEach()гарантирует, что страница загружается перед выполнением каждого теста. Это помогает поддерживать чистую структуру тестов и обеспечивает соблюдение определённых условий перед выполнением каждого теста.

Теперь выполните набор тестов на визуальное сравнение, используя следующую команду:

npx playwright test -g 'Visual'

Изначально тест провалится из-за отсутствия базового изображения (так называемого “золотого файла”). Это ожидаемая ошибка, так как необходимо установить начальный базовый снимок.

npx playwright test -g 'Visual'
Output
. . .

  3 failed
    [chromium] › todo.spec.js:53:3 › Visual comparison › initial state ───────────────────────
    [firefox] › todo.spec.js:53:3 › Visual comparison › initial state ────────────────────────
    [webkit] › todo.spec.js:53:3 › Visual comparison › initial state ────────────────────────

После выполнения команды HTML-отчет откроется в браузере по умолчанию и покажет, что тесты не прошли во всех браузерах. Это произошло из-за отсутствия базовых изображений для сравнения. В отчете будет раздел «Скриншоты», где можно просмотреть сделанные снимки.

Эти начальные скриншоты сохраняются как эталонные изображения в вашем каталоге с тестами следующим образом:

tree tests
Output
. . .

tests
├── example.spec.js
├── todo.spec.js
└── todo.spec.js-snapshots
    ├── Visual-comparison-initial-state-1-chromium-linux.png
    ├── Visual-comparison-initial-state-1-firefox-linux.png
    └── Visual-comparison-initial-state-1-webkit-linux.png

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

await expect(page).toHaveScreenshot('todomvc-initial-state.png');

Это создаст файлы с именами, такими как:

todomvc-initial-state-chromium-linux.png
todomvc-initial-state-firefox-linux.png
todomvc-initial-state-webkit-linux.png

После создания базового скриншота все последующие тесты будут сравнивать текущее состояние интерфейса с этим эталоном.

Завершите работу HTML-отчета с помощью Ctrl-C, затем повторно выполните тест визуальной регрессии:

npx playwright test -g 'Visual'

Вы должны увидеть успешное выполнение тестов, что говорит об отсутствии визуальных расхождений:

Output
. . .

Running 3 tests using 3 workers
  3 passed (5.3s)
. . .

Чтобы продемонстрировать возможности отчетов Playwright для визуальной регрессии, внесите небольшое изменение в ваше приложение. Например, измените цвет заголовка в файле header.jsx:

src/todo/components/header.jsx

import { useCallback } from "react";
import { Input } from "./input";

import { ADD_ITEM } from "../constants";

export function Header({ dispatch }) {
    const addItem = useCallback((title) => dispatch({ type: ADD_ITEM, payload: { title } }), [dispatch]);

    return (
        <header className="header" data-testid="header">
            <h1 style={{color: "blue"}}>todos</h1>
            <Input onSubmit={addItem} label="New Todo Input" placeholder="What needs to be done?" />
        </header>
    );
}

Это изменение меняет цвет текста заголовка на синий, имитируя типичное изменение в процессе разработки.

Выполните тест визуальной регрессии снова:

npx playwright test -g 'Visual'

На этот раз тест не пройдет, так как текущее состояние интерфейса будет отличаться от эталона:

Output
. . .

  3 failed
    [chromium] › todo.spec.js:53:3 › Visual comparison › initial state ───────────────────────
    [firefox] › todo.spec.js:53:3 › Visual comparison › initial state ────────────────────────
    [webkit] › todo.spec.js:53:3 › Visual comparison › initial state ────────────────────────

При сбое теста отчет автоматически откроется в вашем браузере и предоставит детальные сведения. Откройте любой элемент сбоя и прокрутите до раздела «Несоответствие изображений» для сравнения нового скриншота с эталоном. Вам будут предложены следующие вкладки:

  • Diff выделяет затронутые элементы красным;
  • Actual показывает текущее изображение;
  • Expected показывает эталонное изображение;
  • Side by side размещает эталонное и текущее изображения рядом;
  • Slider позволяет интерактивно сравнивать с помощью ползунка.

При сбое теста возможны два варианта действий:

  1. Непреднамеренные изменения: Если визуальные изменения не задумывались, нужно исправить причину и повторить тесты.
  2. Преднамеренные изменения: Если изменения запланированы и должны стать новыми эталонами, обновите эталонные изображения командой:
npx playwright test -g 'Visual' --update-snapshots

Это перегенерирует базовые изображения, синхронизируя их с новым состоянием интерфейса:

Output
. . .

Running 3 tests using 3 workers
[chromium] › todo.spec.js:53:3 › Visual comparison › initial state
/home/ayo/dev/betterstack/demo/react-todo-mvc/tests/todo.spec.js-snapshots/Visual-comparison-initial-state-1-chromium-linux.png is re-generated, writing actual.
[firefox] › todo.spec.js:53:3 › Visual comparison › initial state
/home/ayo/dev/betterstack/demo/react-todo-mvc/tests/todo.spec.js-snapshots/Visual-comparison-initial-state-1-firefox-linux.png is re-generated, writing actual.
[webkit] › todo.spec.js:53:3 › Visual comparison › initial state
/home/ayo/dev/betterstack/demo/react-todo-mvc/tests/todo.spec.js-snapshots/Visual-comparison-initial-state-1-webkit-linux.png is re-generated, writing actual.
  3 passed (5.1s)

. . .

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

Заключение

В этом руководстве вы научились создавать, выполнять и отлаживать сквозные тесты для React-приложения с Playwright. Мы также рассмотрели важность регрессионного тестирования для поддержания визуальной целостности интерфейса и показали, как эффективно реализовать такие тесты с помощью Playwright.

Перевод статьи «Playwright End-to-End Testing: A Step-by-Step Guide».

Оставьте комментарий

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