На сегодняшний день очень распространено использование технологии Ajax в веб-приложениях. Эта технология основана на асинхронных запросах и доставляет много неудобств для разработчиков автоматизированных тестов. Для написания автоматизированных тестов мы используем HtmlUnit. Последняя версия HtmlUnit довольно неплохо позволяет обрабатывать асинхронные запросы, но все же после отправления Ajax запроса на сервер, приходилось вставлять паузу для ожидания ответа от сервера. Это довольно неудобно, поскольку разные запросы обрабатываются разное время. Если выставлять очень большую паузу – то скрипты исполнялись очень долго. Плюс, плохая поддержка JavaScript доставляла массу хлопот. В общем, универсального решения для HtmlUnit пока не найдено и это побудило меня поискать другой инструмент.

Было бы очень неплохо, чтобы данный инструмент включал весь функционал работы с html парсингом как и в HtmlUnit, а также не эмулировал браузеры, а просто работал в браузере или использовал движок браузера.

Раньше мне приходилось исследовать Selenium, но первые версии вызывали множество нареканий и продукт был сырым. На сегодняшний день Selenium RC — это самый распространенный инструмент для разработки автоматизированных скриптов тестирования. Нарастающая популярность данного инструмента обусловлена многими факторами, но самые значимые это:

  1. исполнение скрипта происходит в самом браузере, причем поддерживаются 4 основных браузера
  2. создание теста на основе действий пользователя в браузере (Record/PlayBack) – очень удобно для тестировщиков, которые не сильны в программировании
  3. разработка тестового скрипта на любом из 6-ти языков программирования: .NET, Java, Perl, PHP, Python, Ruby
  4. бесплатный инструмент

При создании первого простого теста мы сразу же столкнулись с проблемой Basic access authentication, а именно, Selenium не позволяет проходить аутентификацию стандартными методами, т.е. соответствующего инструментария просто нет! После прочтения форумов я понял, что решения нет и в основном разработчики Селена говорят, что для тестовой среды аутентификация не нужна – попросите разработчиков отключить аутентификацию, пока вы тестируете систему! Просто замечательно! А если я хочу прогнать тесты на продакшен сервере, где аутентификацию просто нельзя отключать? Пришлось прибегнуть к некоторому хаку. Формат URL позволяет передавать имя пользователя и пароль прямо в запросе, т.е. необходимо открывать URL системы вместе с логином и паролем в следующем формате:

http://username:password@host

Самое интересно, что Mozilla Firefox понимает такой формат, а вот Internet Explorer выдает ошибку:

Ошибка в Internet Explorer

Ошибка в Internet Explorer

Получается, что приложение, которое запрашивает аутентификацию, невозможно будет проверить под Internet Explorer, а этот браузер самый популярный.

И все же вернемся к главной теме. Была поставлена задача – создать набор основных функциональных тестов для системы статистики. Необходимо было реализовать автоматизированный тест для проверки работы функционала «Выбор рекламодателя из списка рекламодателей». Для этого нужно пройти Basic access authentication, потом залогиниться в систему под одним из пользователей, кликнуть ссылку «Show All». В появившемся модальном окне (пример используемого компонента находится тут) пройтись по страницам (пример используемого компонента можно посмотреть тут) и кликнуть на любого рекламодателя. После чего, нажать кнопку «Switch» и проверить, что пользователь переключился на выбранного рекламодателя.

Для примера используется страница с уже открытым модальным окном для выбора рекламодателя. Тестовый скрипт изменен в соответствии с данным примером.

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

public class SeleniumTest {
    public static final String URL = "http://asadykov.gramant.ru.";
    public static void main(String[] args) {
        Selenium browser = new DefaultSelenium("localhost", 4444, "*firefox", URL);
        browser.start();
        browser.open("orders.html");
        browser.windowMaximize();
        browser.click("link=2");
        browser.waitForPageToLoad("30000");
    }
}

Запускаем Селен сервер:

java -jar selenium-server.jar

И запускаем скрипт. После завершения скрипта проверяем страницу, должна загрузиться главная страница нашего сайта. На самом деле клика не было!

Смотрим в консоль сервера:

15:00:17.057 INFO - Command request: getNewBrowserSession[*firefox, http://asadykov.gramant.ru/, ] on session null
15:00:17.057 INFO - creating new remote session
15:00:17.073 INFO - Allocated session 6105471655774f608b8c61a994b12565 for http://asadykov.gramant.ru/, launching...
15:00:17.135 INFO - Preparing Firefox profile...
15:00:20.695 INFO - Launching Firefox...
15:00:24.364 INFO - Got result: OK,6105471655774f608b8c61a994b12565 on session 6105471655774f608b8c61a994b12565
15:00:24.396 INFO - Command request: open[orders.html, ] on session 6105471655774f608b8c61a994b12565
15:00:26.129 INFO - Got result: OK on session 6105471655774f608b8c61a994b12565
15:00:26.144 INFO - Command request: windowMaximize[, ] on session 6105471655774f608b8c61a994b12565
15:00:26.191 INFO - Got result: OK on session 6105471655774f608b8c61a994b12565
15:00:26.207 INFO - Command request: click[link=2, ] on session 6105471655774f608b8c61a994b12565
15:00:26.269 INFO - Got result: OK on session 6105471655774f608b8c61a994b12565

Судя по логам – клик был сделан, сервер не нашел ошибок. Пробуем тоже самое сделать руками – клик проходит, пользователя перебрасывает на главную страницу нашей компании. После чего, я пробовал разными способами реализовать клик с помощью селена, например, так:

browser.click("xpath=//a[text()=2]");

Сервер «съедает» команду, клика нет! Если сделать клик так:

browser.click("id=pageLink10");

То клик проходит. Но я данный тест не могу написать, опираясь на id элемента, поскольку данный атрибут всегда меняется – его меняет wicket компонента приложения. Получается, что либо находить элемент по dom дереву, что очень неудобно и трудоемко, либо… отказываться от Селена.

После долгого изучения api Селена я нашел нестандартный выход:

public class SeleniumTest {
    public static final String URL = "http://asadykov.gramant.ru/";
    public static void main(String[] args) {
        Selenium browser = new DefaultSelenium("localhost", 4444, "*firefox", URL);
        browser.start();
        browser.open("orders.html");
        browser.windowMaximize();
        String link = getLink(browser, "2");
        browser.click(link);
        browser.waitForPageToLoad(30000);
    }
   public static String getLink(Selenium browser, String linkText) {
        String[] links = browser.getAllLinks();
        for (String link : links) {
            if (!link.isEmpty()) {
                String text = browser.getText(link);
                if (text.equals(linkText))
                    return link;
            }
        }
        throw new SeleniumExcepton("Link with text [" + linkText + "] is not detected");
    }
}

Т.е. пишем метод, который перебирает все ссылки на странице и находит ту ссылку, у которой текст это «2». И все работает, клик был сделан.

Выходит так, что действия пользователя не эмулируются 100%, Селен работает через свой драйвер, в котором еще есть ошибки.

В заключении хочу сказать, что искать элементы html с помощью xpath очень неудобно, если нет дополнительных знаний. На сколько все проще сделано в HtmlUnit, где для каждого тега html сделан свой класс с соответствующими методами.

  • Sharing

    Facebooktwittergoogle_plusredditpinterestlinkedinmailby feather