Protractor — это фреймворк для автоматизированного тестирования веб-приложений на Angular и других JavaScript-приложениях. Он построен на основе WebDriverJS, который использует асинхронные операции для взаимодействия с браузером. Управление асинхронностью в тестах Protractor критически важно, и здесь ключевую роль играют callbacks и Promise.
В отличие от синхронного кода, где команды выполняются
последовательно, в Protractor большинство операций с браузером
выполняются асинхронно. Это значит, что результат
операции может быть доступен не сразу, а через некоторое время.
Например, методы element(by.css(...)).getText() или
browser.get(url) возвращают не сам результат, а
объект Promise, который будет разрешён в будущем.
Использование асинхронного подхода позволяет:
Callback — это функция, которая передается в другую
функцию и вызывается после завершения асинхронной операции. В старых
версиях Protractor (до внедрения async/await) активно
использовались callbacks для обработки результатов:
element(by.id('username')).getText().then(function(text) {
console.log('Текст элемента:', text);
});
Здесь функция then принимает callback, который будет
вызван после того, как Promise вернётся с результатом
getText(). Основные моменты:
Проблема глубокой вложенности:
element(by.id('username')).getText().then(function(text) {
element(by.id('password')).getText().then(function(pass) {
element(by.id('login')).click().then(function() {
console.log('Все действия завершены');
});
});
});
Такой подход работает, но быстро становится нечитаемым и трудным для поддержки.
Promise — это объект, который представляет результат асинхронной операции и позволяет управлять последовательностью выполнения без глубокой вложенности.
Простейший синтаксис с использованием Promise:
let usernamePromise = element(by.id('username')).getText();
usernamePromise.then(function(text) {
console.log('Текст пользователя:', text);
});
Основные возможности Promise:
then: обработка успешного завершения.catch: обработка ошибок.finally: выполнение кода независимо от результата.Promise могут быть цепочкой:
element(by.id('username')).getText()
.then(function(text) {
console.log('Пользователь:', text);
return element(by.id('password')).getText();
})
.then(function(password) {
console.log('Пароль:', password);
return element(by.id('login')).click();
})
.then(function() {
console.log('Вход выполнен');
})
.catch(function(err) {
console.error('Ошибка при выполнении действий:', err);
});
Такой подход позволяет писать асинхронный код линейно, избегая глубокой вложенности callbacks.
С выходом Node.js с поддержкой async/await и новых
версий Protractor появилась возможность использовать синтаксис,
имитирующий синхронный код, что повышает читаемость
тестов:
it('должен корректно войти в систему', async function() {
await browser.get('https://example.com/login');
let username = await element(by.id('username')).getText();
console.log('Пользователь:', username);
let password = await element(by.id('password')).getText();
console.log('Пароль:', password);
await element(by.id('login')).click();
console.log('Вход выполнен');
});
Здесь await приостанавливает выполнение функции
до разрешения Promise, что устраняет необходимость
использования цепочек then.
Встроенные ожидания: методы Protractor
автоматически обрабатывают ожидание элементов, но для сложных условий
можно использовать browser.wait() с пользовательским
условием.
Несколько промисов одновременно:
Promise.all([promise1, promise2]) позволяет ждать
завершения нескольких операций параллельно.
let usernamePromise = element(by.id('username')).getText();
let passwordPromise = element(by.id('password')).getText();
Promise.all([usernamePromise, passwordPromise]).then(([user, pass]) => {
console.log('Пользователь:', user, 'Пароль:', pass);
});
catch и
try/catch (при async/await) позволяют
безопасно отлавливать проблемы с асинхронными операциями.async/await.catch или использовать try/catch внутри
async функций.await с каждым Promise —
упрощает чтение тестов и делает их более предсказуемыми.async/await в одном тесте — это может приводить к
неожиданным результатам.Асинхронная природа Protractor требует грамотного обращения с callbacks и Promise. Понимание этих инструментов позволяет создавать надежные, читаемые и масштабируемые тесты, минимизируя риски ошибок и упрощая поддержку кода.