Spec-Zone.ru › Playwright

Утверждения

Введение​

Playwright включает тестовые утверждения в виде функции expect. Чтобы проверить утверждение, вызовите expect(value) и выберите сопоставитель, соответствующий ожидаемому результату. Существует множество универсальных сопоставителей, таких как toEqual, toContain, toBeTruthy, с помощью которых можно проверять любые условия.

expect(success).toBeTruthy();

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

await expect(page.getByTestId('status')).toHaveText('Submitted');

Playwright будет повторно проверять элемент с тестовым идентификатором status, пока найденный элемент не будет содержать текст "Submitted". Элемент будет повторно находиться и проверяться снова и снова, пока условие не будет выполнено или не истечёт время ожидания. Это время ожидания можно передать явно или настроить один раз с помощью параметра testConfig.expect в конфигурации тестов.

По умолчанию время ожидания для утверждений составляет 5 секунд. Подробнее о различных интервалах ожидания.

Утверждения с автоматическими повторами​

Следующие утверждения будут повторяться, пока не будут выполнены или пока не истечёт время ожидания для утверждений. Учтите, что утверждения с повторами асинхронны, поэтому их необходимо await.

Утверждение Описание
await expect(locator).toBeAttached() Элемент присоединён к DOM
await expect(locator).toBeChecked() Флажок установлен
await expect(locator).toBeDisabled() Элемент отключён
await expect(locator).toBeEditable() Элемент доступен для редактирования
await expect(locator).toBeEmpty() Контейнер пуст
await expect(locator).toBeEnabled() Элемент включён
await expect(locator).toBeFocused() Элемент находится в фокусе
await expect(locator).toBeHidden() Элемент не виден
await expect(locator).toBeInViewport() Элемент пересекается с областью просмотра
await expect(locator).toBeVisible() Элемент виден
await expect(locator).toContainText() Элемент содержит текст
await expect(locator).toContainClass() Элемент содержит указанные CSS-классы
await expect(locator).toHaveAccessibleDescription() Элемент имеет соответствующее описание для средств специальных возможностей
await expect(locator).toHaveAccessibleName() Элемент имеет соответствующее имя для средств специальных возможностей
await expect(locator).toHaveAttribute() У элемента есть атрибут DOM
await expect(locator).toHaveClass() У элемента есть указанный CSS-класс
await expect(locator).toHaveCount() Список содержит точное количество дочерних элементов
await expect(locator).toHaveCSS() У элемента есть CSS-свойство
await expect(locator).toHaveId() У элемента есть идентификатор
await expect(locator).toHaveJSProperty() У элемента есть свойство JavaScript
await expect(locator).toHaveRole() У элемента есть определённая роль ARIA
await expect(locator).toHaveScreenshot() Для элемента сделан снимок экрана
await expect(locator).toHaveText() Текст элемента соответствует заданному
await expect(locator).toHaveValue() Поле ввода содержит значение
await expect(locator).toHaveValues() В элементе select выбраны параметры
await expect(locator).toMatchAriaSnapshot() Элемент соответствует снимку Aria
await expect(page).toMatchAriaSnapshot() Страница соответствует снимку Aria
await expect(page).toHaveScreenshot() Для страницы сделан снимок экрана
await expect(page).toHaveTitle() У страницы есть заголовок
await expect(page).toHaveURL() У страницы есть URL
await expect(response).toBeOK() Ответ имеет статус OK

Утверждения без повторов​

Эти утверждения позволяют проверять любые условия, но не выполняют автоматические повторы. Большую часть времени веб-страницы отображают данные асинхронно, и использование утверждений без повторов может привести к нестабильным тестам.

По возможности отдавайте предпочтение утверждениям с автоматическими повторами. Для более сложных утверждений, требующих повторных проверок, используйте expect.poll или expect.toPass.

Утверждение Описание
expect(value).toBe() Значения совпадают
expect(value).toBeCloseTo() Числа приблизительно равны
expect(value).toBeDefined() Значение не равно undefined
expect(value).toBeFalsy() Значение ложно, например false, 0, null и т. д.
expect(value).toBeGreaterThan() Число больше указанного
expect(value).toBeGreaterThanOrEqual() Число больше или равно указанному
expect(value).toBeInstanceOf() Объект является экземпляром класса
expect(value).toBeLessThan() Число меньше указанного
expect(value).toBeLessThanOrEqual() Число меньше или равно указанному
expect(value).toBeNaN() Значение равно NaN
expect(value).toBeNull() Значение равно null
expect(value).toBeTruthy() Значение истинно, то есть не равно false, 0, null и т. д.
expect(value).toBeUndefined() Значение равно undefined
expect(value).toContain() Строка содержит подстроку
expect(value).toContain() Массив или множество содержит элемент
expect(value).toContainEqual() Массив или множество содержит похожий элемент
expect(value).toEqual() Значения похожи: глубокое сравнение и сопоставление с шаблоном
expect(value).toHaveLength() У массива или строки есть длина
expect(value).toHaveProperty() У объекта есть свойство
expect(value).toMatch() Строка соответствует регулярному выражению
expect(value).toMatchObject() Объект содержит указанные свойства
expect(value).toStrictEqual() Значения похожи, включая типы свойств
expect(value).toThrow() Функция выбрасывает ошибку

Асимметричные сопоставители​

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

Сопоставитель Описание
expect.any() Соответствует любому экземпляру класса или примитивному значению
expect.anything() Соответствует чему угодно
expect.arrayContaining() Массив содержит определённые элементы
expect.arrayOf() Массив содержит элементы определённого типа
expect.closeTo() Числа приблизительно равны
expect.objectContaining() Объект содержит определённые свойства
expect.stringContaining() Строка содержит подстроку
expect.stringMatching() Строка соответствует регулярному выражению

Отрицание сопоставителей​

В общем случае можно проверить, что верно обратное, добавив .not перед сопоставителем:

expect(value).not.toEqual(0);
await expect(locator).not.toContainText('some text');

Мягкие утверждения​

По умолчанию невыполненное утверждение прерывает выполнение теста. Playwright также поддерживает мягкие утверждения: невыполненные мягкие утверждения не прерывают выполнение теста, но помечают его как проваленный.

// Make a few checks that will not stop the test when failed...
await expect.soft(page.getByTestId('status')).toHaveText('Success');
await expect.soft(page.getByTestId('eta')).toHaveText('1 day');

// ... and continue the test to check more things.
await page.getByRole('link', { name: 'next page' }).click();
await expect.soft(page.getByRole('heading', { name: 'Make another order' })).toBeVisible();

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

// Make a few checks that will not stop the test when failed...
await expect.soft(page.getByTestId('status')).toHaveText('Success');
await expect.soft(page.getByTestId('eta')).toHaveText('1 day');

// Avoid running further if there were soft assertion failures.
expect(test.info().errors).toHaveLength(0);

Учтите, что мягкие утверждения работают только с тестовым runner Playwright.

Пользовательское сообщение expect​

В качестве второго аргумента функции expect можно указать пользовательское сообщение, например:

await expect(page.getByText('Name'), 'should be logged in').toBeVisible();

Это сообщение будет отображаться в отчётах как для успешных, так и для неуспешных проверок expect, предоставляя дополнительный контекст об утверждении.

При успешной проверке expect может отображаться такой успешный шаг:

✅ should be logged in    @example.spec.ts:18

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

    Error: should be logged in

    Call log:
      - expect.toBeVisible with timeout 5000ms
      - waiting for "getByText('Name')"


      2 |
      3 | test('example test', async({ page }) => {
    > 4 |   await expect(page.getByText('Name'), 'should be logged in').toBeVisible();
        |                                                                  ^
      5 | });
      6 |

Мягкие утверждения также поддерживают пользовательские сообщения:

expect.soft(value, 'my soft assertion').toBe(56);

expect.configure​

Можно создать собственный предварительно настроенный экземпляр expect со значениями по умолчанию, такими как timeout и soft.

const slowExpect = expect.configure({ timeout: 10000 });
await slowExpect(locator).toHaveText('Submit');

// Always do soft assertions.
const softExpect = expect.configure({ soft: true });
await softExpect(locator).toHaveText('Submit');

expect.poll​

С помощью expect.poll можно преобразовать любое синхронное expect в асинхронную проверку с повторными опросами.

Следующий метод будет повторно вызывать указанную функцию, пока она не вернёт HTTP-статус 200:

await expect.poll(async () => {
  const response = await page.request.get('https://api.example.com');
  return response.status();
}, {
  // Custom expect message for reporting, optional.
  message: 'make sure API eventually succeeds',
  // Poll for 10 seconds; defaults to 5 seconds. Pass 0 to disable timeout.
  timeout: 10000,
}).toBe(200);

Также можно задать пользовательские интервалы опроса:

await expect.poll(async () => {
  const response = await page.request.get('https://api.example.com');
  return response.status();
}, {
  // Probe, wait 1s, probe, wait 2s, probe, wait 10s, probe, wait 10s, probe
  // ... Defaults to [100, 250, 500, 1000].
  intervals: [1_000, 2_000, 10_000],
  timeout: 60_000
}).toBe(200);

Можно сочетать expect.soft с expect.poll, чтобы выполнять мягкие утверждения в логике опроса. Это позволяет тесту продолжить выполнение, даже если утверждение внутри опроса не пройдёт проверку.

await expect.soft.poll(async () => {
  const response = await page.request.get('https://api.example.com');
  return response.status();
}).toBe(200);

expect.configure({ soft: true }) также поддерживает цепочки вызовов с expect.poll и полезен, когда нужно повторно использовать настроенный экземпляр.

const softExpect = expect.configure({ soft: true });
await softExpect.poll(async () => {
  const response = await page.request.get('https://api.example.com');
  return response.status();
}).toBe(200);

expect.toPass​

Можно повторять блоки кода, пока они не будут выполнены успешно.

await expect(async () => {
  const response = await page.request.get('https://api.example.com');
  expect(response.status()).toBe(200);
}).toPass();

Также можно задать пользовательские интервалы ожидания и повтора:

await expect(async () => {
  const response = await page.request.get('https://api.example.com');
  expect(response.status()).toBe(200);
}).toPass({
  // Probe, wait 1s, probe, wait 2s, probe, wait 10s, probe, wait 10s, probe
  // ... Defaults to [100, 250, 500, 1000].
  intervals: [1_000, 2_000, 10_000],
  timeout: 60_000
});

Учтите, что по умолчанию toPass имеет время ожидания 0 и не учитывает пользовательское время ожидания expect.

Добавление пользовательских сопоставителей с помощью expect.extend​

Можно расширить утверждения Playwright, добавив пользовательские сопоставители. Эти сопоставители будут доступны в объекте expect.

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

import { expect as baseExpect } from '@playwright/test';
import type { Locator } from '@playwright/test';

export { test } from '@playwright/test';

export const expect = baseExpect.extend({
  async toHaveAmount(locator: Locator, expected: number, options?: { timeout?: number }) {
    const assertionName = 'toHaveAmount';
    let pass: boolean;
    let matcherResult: any;
    try {
      const expectation = this.isNot ? baseExpect(locator).not : baseExpect(locator);
      await expectation.toHaveAttribute('data-amount', String(expected), options);
      pass = true;
    } catch (e: any) {
      matcherResult = e.matcherResult;
      pass = false;
    }

    if (this.isNot) {
      pass =!pass;
    }

    const message = pass
      ? () => this.utils.matcherHint(assertionName, undefined, undefined, { isNot: this.isNot }) +
          '\n\n' +
          `Locator: ${locator}\n` +
          `Expected: not ${this.utils.printExpected(expected)}\n` +
          (matcherResult ? `Received: ${this.utils.printReceived(matcherResult.actual)}` : '')
      : () =>  this.utils.matcherHint(assertionName, undefined, undefined, { isNot: this.isNot }) +
          '\n\n' +
          `Locator: ${locator}\n` +
          `Expected: ${this.utils.printExpected(expected)}\n` +
          (matcherResult ? `Received: ${this.utils.printReceived(matcherResult.actual)}` : '');

    return {
      message,
      pass,
      name: assertionName,
      expected,
      actual: matcherResult?.actual,
    };
  },
});

Теперь в тесте можно использовать toHaveAmount.

import { test, expect } from './fixtures';

test('amount', async () => {
  await expect(page.locator('.cart')).toHaveAmount(4);
});

Совместимость с библиотекой expect​

примечание

Не путайте expect Playwright с библиотекой expect. Последняя не полностью интегрирована с тестовым runner Playwright, поэтому используйте собственный expect Playwright.

Объединение пользовательских сопоставителей из нескольких модулей​

Можно объединить пользовательские сопоставители из нескольких файлов или модулей.

import { mergeTests, mergeExpects } from '@playwright/test';
import { test as dbTest, expect as dbExpect } from 'database-test-utils';
import { test as a11yTest, expect as a11yExpect } from 'a11y-test-utils';

export const expect = mergeExpects(dbExpect, a11yExpect);
export const test = mergeTests(dbTest, a11yTest);
import { test, expect } from './fixtures';

test('passes', async ({ database }) => {
  await expect(database).toHaveDatabaseUser('admin');
});

© 2026 Microsoft
Licensed under the Apache License, Version 2.0.
https://playwright.dev/docs/test-assertions

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API