Ускорение автоматизации тестирования веб-интерфейса за счет применения Python и Selenide

    Одной из задач компании RTL-Service, которая занимается разработкой систем локального позиционирования с высокой точностью и обеспечением голосовой связи по зашифрованному каналу, является разработка веб-клиента:



    В связи с постоянным развитием веб-клиента (оптимизация, появление дополнительных функций), задача минимизации затрат времени тестировщика и разработчика автотестов является особенно актуальной. Далее приводится опыт ускорения разработки UI-тестов путем применения для этого Selenide и Python сотрудниками нашего отдела тестирования.

    Представляется, что Selenide имеет очевидные преимущества. Во-первых, Selenide является верхним программным уровнем Selenium Webdriver, позволяющим сократить время на выполнение стандартных операций Selenium и, как следствие, ускорить написание и поддержку автотестов. Во-вторых, в нашем случае Selenium тесты были написаны на Java, что и обусловило выбор программной платформы на этом же языке.

    Помимо прочего, Selenide “из коробки” имеет ряд таких полезных особенностей как: автоскриншоты завершившихся ошибкой тестов, возможность загрузить в одну строчку или скачать файл, быстрое развертывание тестового окружения (одной строчкой open(«http://rtlservice.com/»)) и множество других. При завершении теста ошибкой в консоли появится примерно следующее:
    Element should not be exist {By.name: infoEdit}
    Element: '<div class="icon btn size-2" name="infoEdit" title="Настройки"></div>'
    Screenshot: file://build/reports/tests/1458565041545.0.png
    

    и полный StackTrace, как обычно.
    В данном случае 1458565041545.0.png и есть скриншот окна браузера, где можно увидеть точное место возникновения проблемы.

    Поскольку основным браузером для нашей системы является Chrome, где основные сценарии тестируются на Debian 7, на первом этапе возможно столкновение с проблемой инициализации веб-драйвера. После проведения теста на разных системах нашими сотрудниками, был сделан вывод о том, что эта проблема относится скорее к операционной системе, нежели к самой платформе. Для ее устранения был создан экземпляр RemoteWebDriver в коде инициализации с применением chromedriver и передан через статичный метод setWebDriver в Selenide. Для реализации этого способа была соблюдена примерно такая последовательность действий:
    1. Установка chromedriver.
    2. Запуск chromedriver не под sudo. По умолчанию он запускается на 127.0.0.1:9515.
    3. Создание драйвера через аннотацию before:
    @Before
    public void openBrowser () throws Exception {
        driver = new RemoteWebDriver(new URL("http://127.0.0.1:9515"), DesiredCapabilities.chrome());
        WebDriverRunner.setWebDriver(driver);
        driver.manage().window().maximize(); // при необходимости разворачиваем браузер
    }

    Кроме того, ещё одним существенным плюсом использования Selenide является наличие расширенных методов по управлению самим элементами в DOM. Если, к примеру, в Selenium все сводится к методу click() с проверкой на isSelected() у элемента, то у Selenide есть возможность выбора чекбоксов/радиокнопок или списков.
    Например, в нашем проекте используется OpenLayers, поэтому для более удобной работы со слоями (включение / отключение) в Selenide можно сделать довольно лаконичную конструкцию, которая снимет выделение со всех чекбоксов:
    for (SelenideElement checkBox : $$(By.tagName("input")).filterBy(Condition.hasAttribute("type", "checkbox"))) {
        checkBox.setSelected(false);
    }
    

    image
    Не менее важным пунктом является использование «умных ожиданий». «Умные ожидания» представляют собой более простой для чтения код без нагромождения WebDriverWait или ожиданий через Thread.sleep с подбором времени появления элемента на глаз.
    В случае с Selenide достаточно написать:

    $(By.id("select-map-div")).waitUntil(Condition.visible, 5000);


    где 5000 — время в миллисекундах, в течении которого Selenide будет ожидать появления элемента.
    На заметку: если вы уверены, что элемент появится в промежутке до 4х секунд, то достаточно использовать только метод should. В этом случае Selenide будет ждать 4 секунды до вывода ошибки. Безусловно, это время можно изменить в конфигурации.

    Таким образом, на таких нюансах, Selenide и позволяет в итоге сэкономить много времени как на написание тестов, так и на их поддержку, как минимум при использовании более очевидной конструкции should по сравнению с assert'ами.
    Более подробно ознакомиться с возможностями Selenide можно в статье разработчика этого инструмента (https://habrahabr.ru/post/274071/).

    Вторая важная деталь в ускорении разработки тестов состоит в использовании Python, который добавляет гибкость тестам и применяется для быстрой разработки дополнительных утилит, облегчающих жизнь тестировщикам.
    Python повышает гибкость тестов за счет своей интерпретируемости, которая позволяет работать с периодически изменяющимся API. То есть, просто вызывая Python скрипт из Java, можно всегда получать актуальные данные без внесения изменений в код теста, будь то события, местоположение, карты или что-то другое.

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

    Из этого пункта также вытекает возможность использовать как виртуальные, так и реальные устройства в процессе тестирования, заменив выборку из базы на массив MAC-адресов необходимых устройств и запустив тест (иногда таким образом удается выявить проблемы и в прошивках устройств).

    Примечательно, что на Python также пишутся скрипты к различным внутренним программам для ручного тестирования, предоставляющие более интерактивную оболочку. Бесспорно, для этого можно применять bash, но, субъективно, у Python порог вхождения ниже и при каких-либо проблемах поправить на нем скрипт будет проще.

    Таким образом, с одной стороны, при использовании Selenide нам удалось повысить скорость разработки автотестов на 30% и значительно облегчить их поддержку, а, с другой, при помощи Python удалось добиться гибкости тестов в динамически изменяющейся системе.

    Авторы: Николай Федоров, Николай Смирнов

    ГК «РТЛ Сервис»

    53,54

    Разработчик системы локального позиционирования

    Поделиться публикацией
    Комментарии 4
      0
      Про базу можете пояснить, почему не ходить в нее с помощью java?
      «То есть, просто вызывая Python скрипт из Java, можно всегда получать актуальные данные без внесения изменений в код теста, будь то события, местоположение, карты или что-то другое.»
      Скрипты на питоне разве не приходится править, если изменился апи?
        0
        Скрипты на питоне править приходится, но перекомпилировать тесты в таком случае нет необходимости
          0
          Python — это фетиш нашего отдела тестирования
          0
          Тег java, рассказ о python… ну ладно, не суть.
          А почему бы не написать пару своих классов-оберток над selenium, и не тащить две платформы плюс библиотеку на тест-стенд и не вызывать питон из джавы?
          Есть же html elements в конце концов, да и в целом селенид не панацея. Посмотрите в сторону selenium+pytest+пара рук, очень удобно, масштабируемо, паралелизируемо и все такое.

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

          Самое читаемое