Уменьшение количества ожиданий

В автоматизированном тестировании веб-приложений чрезмерное использование явных ожиданий (browser.sleep(), ExpectedConditions) может привести к замедлению тестов, нестабильности и трудностям в сопровождении кода. Protractor предоставляет инструменты для минимизации количества ожиданий и оптимизации взаимодействия с элементами страницы.


1. Автоматическое ожидание Angular

Protractor изначально разработан для приложений на Angular. Он умеет автоматически ожидать завершения всех асинхронных операций, таких как HTTP-запросы, таймеры или обновления модели:

element(by.model('user.name')).sendKeys('John');
element(by.binding('user.name')).getText().then(console.log);

В данном примере дополнительное ожидание не требуется — Protractor автоматически дождется, когда модель user.name обновится на странице.

Ключевой момент: для Angular-приложений большинство операций можно выполнять без browser.sleep() или явных ExpectedConditions.


2. Использование ExpectedConditions только при необходимости

ExpectedConditions позволяет задать проверку состояния элемента, например, видимость, кликабельность или присутствие в DOM:

const EC = protractor.ExpectedConditions;
const button = element(by.id('submit'));

browser.wait(EC.elementToBeClickable(button), 5000);
button.click();

Совет: использовать ExpectedConditions только в тех случаях, когда элемент может появляться с задержкой, либо когда требуется убедиться в готовности интерфейса. Чрезмерное ожидание ведет к увеличению времени тестирования.


3. Сокращение browser.sleep()

Прямое использование browser.sleep() часто приводит к недетерминированным тестам. Вместо фиксированной задержки рекомендуется:

  • Проверять видимость элемента через isDisplayed().
  • Использовать browser.wait() с условием.
  • Работать с Angular-процессами, полагаясь на автоматическое ожидание.

Пример замены browser.sleep():

// Неэффективно:
browser.sleep(3000);
element(by.id('menu')).click();

// Эффективно:
const menu = element(by.id('menu'));
browser.wait(EC.visibilityOf(menu), 5000);
menu.click();

4. Асинхронные операции и цепочки промисов

Protractor использует promise-based API, что позволяет уменьшить необходимость явных ожиданий через корректное управление цепочками промисов:

element(by.id('username')).sendKeys('user')
    .then(() => element(by.id('password')).sendKeys('pass'))
    .then(() => element(by.id('login')).click());

В новых версиях Protractor с async/await код становится ещё чище:

await element(by.id('username')).sendKeys('user');
await element(by.id('password')).sendKeys('pass');
await element(by.id('login')).click();

В обоих случаях нет необходимости в browser.sleep(), так как операции выполняются последовательно, а Protractor автоматически ждёт завершения действий Angular.


5. Настройка таймаутов

Для уменьшения количества ожиданий важно правильно настроить глобальные таймауты:

browser.manage().timeouts().implicitlyWait(5000);

Примечание: implicitlyWait задаёт максимальное время поиска элементов. Если элемент найден раньше, тест продолжает выполнение без задержки. Это сокращает лишние ожидания, но не заменяет проверку видимости или кликабельности через ExpectedConditions.


6. Ленивая загрузка элементов

Иногда элементы появляются динамически после AJAX-запросов. Вместо ожидания фиксированной задержки используется ленивый поиск элементов:

const dynamicElement = element(by.css('.dynamic-item'));

await browser.wait(async () => await dynamicElement.isPresent(), 5000);
await dynamicElement.click();

Такой подход гарантирует выполнение действия только после появления элемента, без лишней паузы.


7. Совмещение стратегий

Для уменьшения ожиданий часто применяют комбинацию методов:

  • Полагаться на автоматическое ожидание Angular.
  • Использовать ExpectedConditions для критических элементов.
  • Избегать browser.sleep().
  • Применять асинхронные цепочки через async/await.
  • Настраивать таймауты поиска и взаимодействия.

Эта стратегия обеспечивает стабильность тестов при минимальном времени выполнения.


8. Практическая рекомендация

Для снижения количества ожиданий и ускорения тестов:

  • Проверять необходимость каждого явного ожидания.
  • Переписывать участки с browser.sleep() на комбинацию browser.wait + ExpectedConditions.
  • Использовать локаторы с минимальной задержкой, избегая глобальных селекторов, которые могут искать элементы дольше.
  • Сегментировать тесты на независимые блоки, где каждый блок сам ожидает готовности элементов.

Эффективное управление ожиданиями в Protractor позволяет создавать быстрые и надежные автоматизированные тесты, минимизируя риски фальшиво-положительных или фальшиво-отрицательных результатов и сокращая общее время тестирования.