Как работает WebDriver

Protractor — это фреймворк для автоматизированного тестирования веб-приложений на Angular и не только. Его ядро строится на WebDriver, стандарте взаимодействия с браузерами, который обеспечивает управление веб-страницами на уровне пользователя. Понимание работы WebDriver является ключевым для эффективного использования Protractor и написания надёжных тестов.


Архитектура WebDriver

WebDriver представляет собой протокол, позволяющий управлять браузером через HTTP-запросы. Архитектура включает несколько ключевых компонентов:

  • Клиентская библиотека (Client Library) В Protractor это JavaScript-обертка над WebDriver API. Она предоставляет удобные методы для поиска элементов, выполнения действий, ожидания состояний и проверки условий.

  • Сервер WebDriver (WebDriver Server / Selenium Server) При использовании Protractor напрямую или через Selenium Server запросы от клиентской библиотеки отправляются на сервер, который преобразует их в команды для конкретного браузера.

  • Браузерный драйвер (Browser Driver) Каждый браузер имеет свой драйвер: chromedriver для Chrome, geckodriver для Firefox и т.д. Драйвер принимает команды сервера и управляет браузером на низком уровне, эмулируя действия пользователя.

Важно: WebDriver абстрагирует различия между браузерами, предоставляя единый API, что делает тесты кросс-браузерными.


Сессии и команды WebDriver

При запуске теста Protractor инициирует сессию WebDriver, которая представляет собой уникальное соединение с браузером. Каждая сессия имеет идентификатор и хранит состояние браузера (открытые страницы, куки, локальное хранилище).

Команды WebDriver делятся на несколько категорий:

  • Навигация: переход по URL, обновление страницы, возврат назад или вперёд в истории браузера.

    browser.get('https://example.com');
    browser.navigate().back();
    browser.refresh();
  • Манипуляции с элементами: ввод текста, клик, выбор опций, скроллинг.

    element(by.css('#input')).sendKeys('тест');
    element(by.buttonText('Отправить')).click();
  • Состояние страницы и ожидания: проверка видимости, доступности элементов, ожидание загрузки Angular.

    let button = element(by.id('submit'));
    browser.wait(protractor.ExpectedConditions.elementToBeClickable(button), 5000);
  • Работа с окнами и фреймами: переключение между вкладками, окнами, iframe.

Каждая команда отправляется через HTTP-запрос к драйверу, который исполняет действие и возвращает результат. Этот процесс асинхронный, поэтому в Protractor все операции поддерживают промисы и методы async/await.


Асинхронная природа WebDriver

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

Пример правильной синхронизации:

it('должен открыть страницу и проверить заголовок', async () => {
    await browser.get('https://example.com');
    let title = await browser.getTitle();
    expect(title).toEqual('Example Domain');
});

Важно понимать, что без await или then результат команды может быть не получен к моменту проверки, что приведёт к нестабильным тестам.


Особенности взаимодействия с Angular

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

Если тестируется не-Angular приложение, нужно явно отключить эту синхронизацию:

browser.waitForAngularEnabled(false);

Логирование и отладка

WebDriver позволяет отслеживать каждый шаг теста. В Protractor можно включить логирование HTTP-запросов и команд, что помогает отлаживать ошибки взаимодействия с браузером.

Также существует возможность делать скриншоты при падении теста:

browser.takeScreenshot().then((png) => {
    require('fs').writeFileSync('screenshot.png', png, {encoding: 'base64'});
});

Ограничения и нюансы WebDriver

  • Некоторые действия могут вести себя по-разному в разных браузерах (например, drag-and-drop).
  • Высокая нагрузка на сервер WebDriver при параллельном запуске большого числа тестов требует корректной настройки Selenium Grid.
  • Асинхронные операции должны быть строго синхронизированы через await, иначе тесты будут нестабильны.

Ключевые моменты

  • WebDriver — это протокол взаимодействия с браузером через HTTP-запросы.
  • Protractor использует клиентскую библиотеку, Selenium Server и драйверы браузеров для управления страницами.
  • Все действия асинхронные, поэтому важно использовать async/await или промисы.
  • Для Angular-приложений Protractor автоматически синхронизируется с состоянием приложения, но для других страниц это нужно делать вручную.
  • Логирование и скриншоты помогают диагностировать ошибки на этапе тестирования.

Эффективное использование WebDriver позволяет создавать надёжные, повторяемые и кросс-браузерные тесты, минимизируя влияние динамических изменений страниц и особенностей конкретного браузера.