Лучшие практики Playwright
Урок: Лучшие практики Playwright
Введение
Когда ты только начинаешь писать тесты в Playwright, всё кажется простым: открыл страницу, нажал кнопку, проверил результат — готово.
Но со временем тестов становится больше. Они начинают:
- падать без очевидной причины;
- зависеть друг от друга;
- ломаться при малейших изменениях интерфейса.
Представь, что ты строишь дом. Сначала можно просто складывать кирпичи, и всё будет выглядеть нормально. Но если не соблюдать правила, со временем стены начнут трескаться.
С тестами то же самое. Можно написать «работающий код», но без правильной структуры он быстро станет нестабильным и сложным в поддержке.
Лучшие практики — это не про «красоту кода», а про стабильность, предсказуемость и удобство работы в долгую.
Пиши тесты как сценарии пользователя
Хороший тест — это не набор технических действий, а понятный сценарий.
Плохо:
await page.click('#btn-login');
await page.fill('#input1', 'user');
await page.fill('#input2', '1234');
Лучше:
await page.getByPlaceholder('Логин').fill('user');
await page.getByPlaceholder('Пароль').fill('1234');
await page.getByRole('button', { name: 'Войти' }).click();
Разница в том, что:
- код читается как действия пользователя;
- легче понять, что происходит;
- тест проще поддерживать.
Важно стремиться к тому, чтобы тест можно было «прочитать вслух».
Используй устойчивые селекторы
Одна из самых частых причин падения тестов — нестабильные селекторы.
Плохо:
await page.click('.btn-primary');
Почему плохо:
- класс может измениться;
- дизайн поменяется — тест сломается.
Лучше:
await page.getByRole('button', { name: 'Войти' }).click();
Или:
await page.getByTestId('login-button').click();
Идея в том, что селектор должен быть:
- стабильным;
- не зависеть от верстки;
- понятным.
Не используй явные ожидания (wait)
Новички часто делают так:
await page.waitForTimeout(2000);
Это плохая практика.
Почему:
- тесты становятся медленными;
- иногда 2 секунд недостаточно;
- иногда это лишнее ожидание.
Playwright уже умеет ждать автоматически:
await page.click('button');
Он сам подождёт, пока элемент станет доступным.
Если нужно ждать, лучше использовать:
await expect(page.getByText('Успех')).toBeVisible();
Это проверяет условие, а не просто «ждёт время».
Разделяй логику через Page Object
Когда тесты растут, код начинает дублироваться.
Например:
await page.fill('#login', 'user');
await page.fill('#password', '1234');
await page.click('button');
Если это используется в разных тестах — лучше вынести в отдельный класс.
class LoginPage {
constructor(page) {
this.page = page;
}
async login(username, password) {
await this.page.fill('#login', username);
await this.page.fill('#password', password);
await this.page.click('button');
}
}
Использование:
const loginPage = new LoginPage(page);
await loginPage.login('user', '1234');
Это делает код:
- чище;
- переиспользуемым;
- удобным для изменений.
Не смешивай тест и логику
Плохой тест:
test('логин', async ({ page }) => {
await page.goto('/login');
await page.fill('#login', 'user');
await page.fill('#password', '1234');
await page.click('button');
await page.waitForTimeout(2000);
const text = await page.textContent('.message');
if (text === 'Успех') {
console.log('OK');
}
});
Здесь:
- логика проверки смешана с тестом;
- нет явного утверждения.
Лучше:
await expect(page.getByText('Успех')).toBeVisible();
Тест должен:
- описывать поведение;
- проверять результат;
- не содержать лишней логики.
Используй expect вместо ручных проверок
Плохо:
let text = await page.textContent('.message');
if (text !== 'Успех') {
throw new Error('Ошибка');
}
Лучше:
await expect(page.getByText('Успех')).toBeVisible();
Почему:
expectуже встроен;- даёт понятные ошибки;
- автоматически ждёт результат.
Изолируй тесты
Каждый тест должен быть независимым.
Плохо:
- тест зависит от предыдущего;
- данные «протекают» между тестами.
Playwright решает это через context:
test('пример', async ({ page }) => {
await page.goto('https://example.com');
});
Каждый тест получает:
- новый контекст;
- чистую сессию.
Важно не ломать эту изоляцию вручную.
Делай тесты быстрыми
Медленные тесты — это проблема.
Причины:
- лишние ожидания;
- повторяющиеся действия;
- работа с UI там, где можно через API.
Например, вместо логина через UI в каждом тесте можно:
- создать пользователя через API;
- использовать сохранённую сессию.
Это ускоряет тесты в разы.
Добавляй осмысленные проверки
Плохой тест:
await page.click('button');
Он ничего не проверяет.
Хороший тест:
await page.click('button');
await expect(page.getByText('Успешно')).toBeVisible();
Тест должен не просто выполнять действия, а проверять результат.
Где это применяется на практике
Лучшие практики важны в реальных проектах:
- большие тестовые наборы;
- CI/CD;
- командная разработка;
- долгосрочная поддержка.
Без них:
- тесты становятся нестабильными;
- сложно находить ошибки;
- падает доверие к автотестам.
С ними:
- тесты работают предсказуемо;
- код легче поддерживать;
- команда быстрее развивается.
Итоговое понимание
Лучшие практики Playwright — это не набор правил ради правил.
Это подход к написанию тестов, который делает их:
- стабильными;
- читаемыми;
- независимыми;
- быстрыми.
Ключевая идея в том, что тесты — это тоже код, и к ним применяются те же принципы качества.
Хорошие тесты не просто «работают сегодня», а остаются понятными и надёжными через месяцы и годы.