Утверждения
Введение
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 их.
Утверждения без автоматического повтора
Эти утверждения позволяют проверять любые условия, но не повторяют автоматически. В большинстве случаев веб-страницы отображают информацию асинхронно, и использование утверждений без автоматического повтора может привести к ненадежному тесту.
Предпочитайте утверждения с автоматическим повтором всякий раз, когда это возможно. Для более сложных утверждений, которые необходимо повторять, используйте 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(value).any() | Соответствует любому экземпляру класса/примитива |
| expect(value).anything() | Соответствует чему угодно |
| expect(value).arrayContaining() | Массив содержит определенные элементы |
| expect(value).closeTo() | Число приблизительно равно |
| expect(value).objectContaining() | Объект содержит определенные свойства |
| expect(value).stringContaining() | Строка содержит подстроку |
| expect(value).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); Обратите внимание, что мягкие утверждения работают только с исполнителем тестов Playwright.
Настройка собственного сообщения для expect
Вы можете указать пользовательское сообщение expect в качестве второго аргумента функции expect, например:
await expect(page.getByText('Name'), 'should be logged in').toBeVisible(); Это сообщение будет отображаться в отчетах, как для прошедших, так и для не прошедших утверждений, предоставляя дополнительный контекст утверждению.
При прохождении утверждения вы можете увидеть успешный шаг примерно так:
✅ should be logged in @example.spec.ts:18
При неудачном утверждении ошибка будет выглядеть так:
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 в асинхронную, используя expect.poll.
Следующий метод будет повторять указанную функцию до тех пор, пока она не вернет 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.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 { Page, 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 {
await baseExpect(locator).toHaveAttribute('data-amount', String(expected), options);
pass = true;
} catch (e: any) {
matcherResult = e.matcherResult;
pass = false;
}
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
примечаниеНе путайте утверждения Playwright
expectс библиотекойexpect. Последняя не полностью интегрирована с исполнителем тестов Playwright, поэтому убедитесь, что используете собственные утверждения Playwrightexpect.
Комбинирование пользовательских утверждений из нескольких модулей
Вы можете комбинировать пользовательские утверждения из нескольких файлов или модулей.
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');
});
© 2024 Microsoft
Licensed under the Apache License, Version 2.0.
https://playwright.dev/docs/test-assertions