Кастомизация assertions
Урок: Кастомизация assertions
Введение
Когда ты только начинаешь писать тесты, утверждения (expect) выглядят просто и понятно: проверил текст, убедился, что элемент видим — и всё работает.
Но по мере роста проекта возникает проблема. Проверки начинают повторяться. Например:
- в каждом тесте ты проверяешь, что пользователь залогинен;
- в каждом тесте проверяешь одинаковые сообщения;
- везде пишешь похожие
expect.
Представь, что ты каждый раз вручную проверяешь одно и то же: открыл страницу, посмотрел, есть ли аватар, есть ли имя пользователя, есть ли кнопка выхода. Это начинает утомлять.
Хочется сказать: «просто проверь, что пользователь авторизован».
Именно для этого нужна кастомизация assertions — возможность создавать свои проверки и настраивать поведение стандартных.
Это делает тесты:
- короче;
- понятнее;
- более поддерживаемыми.
Зачем кастомизировать assertions
Рассмотрим повторяющийся код:
await expect(page.getByText('Добро пожаловать')).toBeVisible();
await expect(page.getByTestId('avatar')).toBeVisible();
await expect(page.getByRole('button', { name: 'Выйти' })).toBeVisible();
Такая проверка может встречаться в десятках тестов.
Проблема:
- код дублируется;
- если логика изменится — нужно менять везде;
- тесты становятся громоздкими.
Хочется заменить это на что-то вроде:
await expectUserLoggedIn(page);
Это и есть идея кастомных assertions.
Настройка стандартных assertions
Первый уровень кастомизации — это настройка поведения expect.
Например, можно изменить таймаут:
await expect(page.getByText('Успешно')).toBeVisible({ timeout: 10000 });
Здесь:
- мы увеличили время ожидания до 10 секунд.
Это полезно, если:
- данные грузятся долго;
- есть анимации;
- нестабильное окружение.
Также можно использовать глобальные настройки:
test.use({
expect: {
timeout: 10000,
},
});
Теперь все expect будут ждать дольше.
Использование expect с опциями
Можно добавлять дополнительные параметры:
await expect(page.getByText('Ошибка')).toBeVisible({
timeout: 5000,
});
Или проверять частичное совпадение текста:
await expect(page.getByRole('heading')).toContainText('Добро');
Здесь:
- не обязательно точное совпадение;
- проверяется наличие части текста.
Создание собственных функций-assertions
Самый простой способ кастомизации — вынести проверки в функцию.
async function expectUserLoggedIn(page) {
await expect(page.getByText('Добро пожаловать')).toBeVisible();
await expect(page.getByTestId('avatar')).toBeVisible();
}
Использование:
await expectUserLoggedIn(page);
Что это даёт:
- код становится короче;
- логика централизована;
- изменения делаются в одном месте.
Добавление параметров в кастомные проверки
Можно сделать проверки более гибкими:
async function expectUserName(page, name) {
await expect(page.getByTestId('username')).toHaveText(name);
}
Использование:
await expectUserName(page, 'Stepan');
Теперь функция работает для разных данных.
Кастомные assertions через expect.extend
Playwright (через expect из Jest) позволяет расширять assertions.
Пример:
import { expect } from '@playwright/test';
expect.extend({
async toBeLoggedIn(page) {
const locator = page.getByTestId('avatar');
const isVisible = await locator.isVisible();
if (isVisible) {
return {
pass: true,
message: () => 'Пользователь залогинен',
};
} else {
return {
pass: false,
message: () => 'Пользователь не залогинен',
};
}
},
});
Использование:
await expect(page).toBeLoggedIn();
Разберём:
- мы добавили новый метод
toBeLoggedIn; - внутри описали логику проверки;
- теперь можно использовать его как стандартный expect.
Когда стоит использовать extend, а когда функции
Есть два подхода:
Функции:
await expectUserLoggedIn(page);
Подходят, когда:
- нужна простая логика;
- не требуется интеграция в expect.
expect.extend:
await expect(page).toBeLoggedIn();
Подходит, когда:
- хочется единый стиль;
- нужно писать более «нативные» проверки;
- проект большой и стандартизированный.
Улучшение читаемости тестов
Сравним два варианта.
Без кастомизации:
await expect(page.getByText('Добро пожаловать')).toBeVisible();
await expect(page.getByTestId('avatar')).toBeVisible();
await expect(page.getByRole('button', { name: 'Выйти' })).toBeVisible();
С кастомизацией:
await expectUserLoggedIn(page);
Или:
await expect(page).toBeLoggedIn();
Второй вариант:
- проще читается;
- быстрее воспринимается;
- ближе к бизнес-логике.
Где это используется на практике
Кастомные assertions особенно полезны:
- в больших проектах;
- при командной разработке;
- при повторяющихся сценариях;
- в e2e тестах с бизнес-логикой.
Например:
- проверка авторизации;
- проверка состояния корзины;
- проверка ролей пользователя;
- проверка отображения данных.
Итоговое понимание
Кастомизация assertions — это способ сделать проверки более удобными, читаемыми и переиспользуемыми.
Ключевая идея в том, что тест должен описывать поведение на уровне смысла, а не деталей.
Вместо: «проверь текст, проверь кнопку, проверь аватар»
мы приходим к: «проверь, что пользователь залогинен».
Это:
- упрощает код;
- снижает дублирование;
- делает тесты ближе к реальным сценариям.
Хорошие assertions — это не просто проверки, а язык, на котором тесты «разговаривают» с приложением.