В тестировании веб-приложений с использованием Protractor большинство операций с элементами страницы выполняются асинхронно. Любое взаимодействие с браузером — поиск элемента, клик, ввод текста — возвращает Promise, что требует тщательной работы с обработкой ошибок. Ошибки в асинхронном коде могут приводить к зависанию тестов, ложным срабатываниям и трудночитаемым логам.
Ключевая особенность: Protractor построен на
WebDriverJS и использует промисы для управления асинхронными операциями.
Даже простые действия, такие как
element(by.css('.btn')).click(), возвращают Promise,
который может быть отклонён при проблемах с DOM или синхронизацией.
try/catch с async/awaitСамый читаемый способ работы с асинхронным кодом в Protractor —
использование async/await. При этом ошибки можно
перехватывать с помощью стандартного try/catch.
it('должен кликнуть на кнопку и обработать ошибку', async () => {
try {
const button = element(by.css('.submit'));
await button.click();
} catch (error) {
console.error('Ошибка при клике на кнопку:', error.message);
}
});
Особенности:
try/catch ловит ошибки выполнения Promise, включая
NoSuchElementError и
ElementNotInteractableError..catch()Если используется цепочка промисов без async/await,
ошибки обрабатываются через метод .catch():
element(by.css('.submit')).click()
.then(() => console.log('Клик выполнен'))
.catch(error => console.error('Ошибка при клике:', error.message));
Особенности:
.catch()..catch() приводят к unhandled promise
rejection и падению теста.В процессе тестирования часто встречаются специфические ошибки WebDriver:
Для управления этими ошибками можно использовать ожидания (ExpectedConditions) и оборачивать действия в try/catch:
const EC = protractor.ExpectedConditions;
const submitButton = element(by.css('.submit'));
try {
await browser.wait(EC.elementToBeClickable(submitButton), 5000);
await submitButton.click();
} catch (error) {
if (error.name === 'TimeoutError') {
console.error('Кнопка не стала кликабельной в течение 5 секунд');
} else {
console.error('Неизвестная ошибка при клике:', error.message);
}
}
Ошибки могут возникать не только при действиях, но и при проверках состояния элементов:
const title = element(by.css('h1'));
try {
const text = await title.getText();
expect(text).toBe('Добро пожаловать');
} catch (error) {
console.error('Ошибка при проверке заголовка:', error.message);
}
Рекомендации:
try/catch, если требуется
дополнительная обработка.Для анализа сбоев полезно автоматически делать скриншоты при исключениях:
async function takeScreenshot(filename) {
const png = await browser.takeScreenshot();
const fs = require('fs');
fs.writeFileSync(filename, png, { encoding: 'base64' });
}
try {
await element(by.css('.submit')).click();
} catch (error) {
console.error('Ошибка при клике:', error.message);
await takeScreenshot('error.png');
}
Преимущества:
await вместо простого возврата
промиса, чтобы ошибки не терялись.try/catch с
логированием.ExpectedConditions для предсказуемости
взаимодействий.При работе с несколькими элементами стоит использовать Promise.all с обработкой ошибок:
const buttons = [element(by.id('btn1')), element(by.id('btn2'))];
try {
await Promise.all(buttons.map(btn => btn.click()));
} catch (error) {
console.error('Ошибка при клике на один из элементов:', error.message);
}
Особенности:
Promise.allSettled:const results = await Promise.allSettled(buttons.map(btn => btn.click()));
results.forEach((result, index) => {
if (result.status === 'rejected') {
console.error(`Ошибка при клике на кнопку ${index + 1}:`, result.reason.message);
}
});
Эффективная обработка ошибок в Protractor обеспечивает стабильность тестов, упрощает диагностику и предотвращает ложные падения. Ключевой принцип — не игнорировать отклонённые промисы и всегда предусматривать план действий при ошибках.