Избавляемся от ExpectedConditions в тестах C# Selenium WebDriver |
13.10.2020 00:00 |
Автор: Баз Дейкстра (Bas Djikstra) Если вы пишете тесты Selenium на C#, то, возможно, заметили, что начиная с версии 3.11 ряд часто используемых штук помечен как устаревший – в частности, PageFactory и класс ExpectedConditions. Для тех, кто не знает, почему это произошло – вот объяснение Джима Эванса, основного разработчика связки Selenium C#. Все это перемещено в новое место и доступно в форме отдельных пакетов NuGet (DotNetSeleniumExtras.PageObjects и DotNetSeleniumExtras.WaitHelpers, соответственно). Когда я писал эту статью, этот репозиторий никто не поддерживал – а следовательно, поддержка недоступна, и будущее его туманно. Пока с этим нет проблем – вы все еще можете использовать устаревшие классы или пользоваться пакетами DotNetSeleniumExtras. Однако я считаю, что тут есть риск положиться на код, который по большей части не поддерживается. В моем случае с PageFactory нет проблем – я, как правило, все равно этим не пользуюсь. Другое дело с ExpectedConditions. Когда я пишу автоматизацию на Selenium и обучаю ей, я в основном следую подходу, который описывал несколько лет назад здесь. Он все еще работает, он читабелен, его легко поддерживать и объяснить, и он был эффективен в множестве различных проектов, с которыми я работал. Однако этот подход полагается на использование ExpectedConditions, и это все чаще и чаще меня беспокоит. Поэтому, готовясь к тренингу, я начал искать альтернативу своим оберточным методам на C#. Оказалось, что C# предлагает для этого элегантный способ прямо из коробки в форме лямбда-выражений. Лямбда-выражения (также известные как анонимные функции) – это функции, не привязанные к идентификатору. Их можно передавать как аргумент в функцию более высокого порядка. Концепция зародилась из функционального программирования (которым я, кстати, давненько не занимался), но уже давно является частью C#. Между прочим, лямбда-выражения доступны и в Java, начиная с Java8, если вы не работаете с C#. Посмотрим на примере. Вот так я бы реализовал свой детализированный оберточный метод через стандартный метод SendKeys() Selinium, который учитывает синхронизацию и работу с исключениями, используя ExpectedConditions: public void SendKeys(By by, string valueToType) Та же самая обертка теперь передает наше собственное лямбда-выражение как аргумент метода Until() вместо метода в ExpectedConditions: public void SendKeys(By by, string valueToType) Документация Selenium гласит, что метод Until() регулярно (с изменяемым интервалом, по умолчанию 500 миллисекунд) оценивает лямбда-выражение, пока не будет применимо одно из условий:
Поэтому я создал лямбда-выражение именно таким. Прежде чем кликнуть по элементу, я хочу дождаться, пока он станет кликабельным. Кликабельность я определяю как видимость (выраженную через свойство Displayed) и доступность (свойство Enabled). Если оба они верны, я возвращаю элемент, в прочих случаях – null. Если это происходит до таймаута, я очищаю текстовое поле и использую стандартный метод SendKeys() для ввода значения. Если происходит WebDriverTimeOutException, я учитываю это соответственно – в этом случае падением теста с внятным сообщением. Да, такое внедрение моих вспомогательных методов немного перегружает мой код, но это небольшая плата за то, чтобы не рассчитывать на библиотеку, которая больше не поддерживается, и чье будущее туманно. К тому же я определяю этих помощников в едином классе, и поэтому это затрагивает только одну часть моего кода. Page Objects и тестовый код остаются без изменений. В этом репозитории находится несколько рабочих примеров тестов, которые написаны для демо-приложения ParaBank. Это обновленная версия решения, описанного здесь. |