вторник, 4 ноября 2014 г.

Как снять скриншот с элемента, который находится за областью видимости окна, не совершая с ним действий

Если необходимо совершить какое-то действие с веб-элементом на странице, Selenium скроллирует страницу автоматически таким образом, что элемент становится видимым. Если же нужно, например, снять скиншот не выполняя никаких действий, то можно воспользоваться следующим методом:

((Locatable) webElement).getCoordinates().inViewPort();

или

webDriver.executeScript("arguments[0].scrollIntoView(true);", webElement);

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

Второй способ - навести мышку на элемент, для этого нужно выполнить следующий код:

Actions actions = new Actions(webDriver);
actions.moveToElement(webElement).perform();

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






четверг, 2 октября 2014 г.

Selenium: как установить время поиска элемента или неявные ожидания

Selenium WebDriver передает управление сразу после выполнения команды, не дожидаясь какого-либо результата своих действий. То есть если Вы выполните клик по ссылке, а потом поиск элемента на странице, находящейся по этой ссылке, то Selenium не будет ждать загрузки страницы после клика, а сразу начнет поиск. Выглядит так, что этот механизм не должен работать, ведь страница еще не загрузилась и тест упадет, но по факту это работает благодаря механизму неявных ожиданий (implicit wait). WebDriver будет искать новый элемент в течение какого-то установленого времени (по умолчанию обычно 60 секунд), это не значит, что он просто подождет минуту и потом пойдет искать элемент. Это значит, что в течение 60 секунд с определенной периодичностью драйвер будет выполнять поиск элемента и только если за все это время найти элемент не удастся он упадет с ошибкой NoSuchElementException.
Методы findElement и findElements асинхронные, чтобы включить для них механизм неявного ожидания можно выполнить следующую команду:

driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);

После выполнения этой команды методы findElement и findElements будут пытаться найти элемент в течение 10 секунд и если ему это не удастся, выбросит исключение NoSuchElementException.

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

Если поставить значение implicitlyWait  переменной равное нулю, то веб драйвер попытается найти элемент один раз и в случае неудачи сразу выбросить исключение. Это может быть уместно, если, например, у Вас в коде уже отрабатывают методы по ожиданию полной загрузки страницы. В таком случае смысла ждать еще и внутри методов поиска элемента уже нет.

Итак, механизм неявных ожиданий (implicity waits) позволяет определить таймаут, в течение которого Selenium WebDriver  будет осуществлять поиск элемента.элементов.

среда, 24 сентября 2014 г.

Если тест зависает при попытке кликнуть на элемент, по клику на который должен открыться popup

Java Selenium WebDriver  испытывает некоторые трудности при обращении с элементами, при клике на которых открывается PopUp (всплывающее окно).
Так например, если сделать обычный клик webelement.click() по такому элементу, то тест зависнет и не упадет ни по таймауту ни по каким другим условиям. Можно лишь закрыть браузер вручную или остановить процесс. Такой эффект появляется только для некоторых сочетаний версий браузера-вебдрайвера-сайта, но тем не менее для меня в свое время это было огромной проблемой.

Чтобы клик проходил нормально, и ничего не зависало, можно нажимать на кнопку с помощью следующего джаваскрипта:

WebElement element;
//...
JavascriptExecutor executor = (JavascriptExecutor) getDriver();
        executor.executeScript("var el=arguments[0]; setTimeout(function() { el.click(); }, 100);", element);

Эта функция точно также кликнет по элементу, как и обычный click().

суббота, 29 марта 2014 г.

Несоответствие версии Selenium версии браузера (Chrome, Firefox и другие)

Одна из проблем работы с селениум заключается в том, что очень часто последняя версия Selenium Web Driver не работает с последними версиями браузеров. В такой ситуации выходов может быть несколько:
1) Подождать пока обновится драйвер для Вашего браузера. Как правило адаптация под новые версии добавляется довольно быстро. Особенно это касается firefox, потому что драйвер для него - это одна из основных частей самого продукта Selenium 2.0.
2) Тестировать на старой версии браузера. Для большинства приложений небольшое различие версий браузера не приводит к каким то фатальным проблемам. Поэтому если у Вас обычное корпоративное приложение или сайт, не использующие самые-самые последние возможности браузеров, то фатальных проблем быть не должно. Просто делаем даунгрэйд браузера и гоняем тесты не на самой последней версии.
Как обновить браузер на более старую версию?
Для Firefox можно запретить обновление в настройках (Firefox->Options->Advanced->Update) - Ставите галку, чтобы файрфокс не проверял наличие обновлений и убираете галку использования фонового сервиса для установки обновлений.

После этого скачиваете нужную версию браузера и устанавливаете поверх существующей (можно даже не удалять существующую)
Для Google Chrome ставите нужную версию и запрещаете обновления. Как запретить обновляться хрому, можете почитать тут.
Как правило, если версии не имеют сильных различий, то обновление браузера может пройти безболезненно. Но если же вдруг почему-то тесты перестали запускаться с примерно такой ошибкой - надо подумать о соответствии драйвера и браузера:
Hit exception trying to create new WebDriver instance: org.openqa.selenium.WebDriverException: Failed to connect to binary FirefoxBinary(C:\Program Files\Mozilla Firefox\firefox.exe) on port 7055;
 Узнать, с какой версией браузера может работать драйвер можно, поискав в описании драйвера список поддерживаемых версий. Например, для хрома описание поддерживаемых версий можно найти здесь.



суббота, 15 марта 2014 г.

Решение проблемы нехватки места на диске с помощью Junction

    Иногда происходит так, что место на диске С:\ заканчивается в не очень подходящий момент. И если возможности ничего удалить нет, а место получить нужно, то ситуация не очень приятная. Да, во многих программах можно настроить папку установки и\или место хранения каких-то используемых файлов. Но это работает не для всех. А еще это может быть виртуальная машина, на которой ничего такого не стоит, но места уже нет на системном диске.

    В таком случае очень поможет поддержка символических ссылок на каталоги, которая уже довольно давно появилась в Windows (с версии Windows 2000).

    В чем суть этой технологии. На другом диске создается папка - копия существующей. А с исходного диска файлы удаляются и создается символическая ссылка. После этого при обращении пользователя\программы\системы к файлу на исходном диске происходит работа с этим файлом - "копией" (которая теперь является оригиналом). 

    Стандартными средствами Windows  этого сделать нельзя. Но есть бесплатная программа Junction, которую можно скачать здесь. С помощью неё можно легко и просто создать символическую ссылку на папку. Это консольное приложение с очень небольшим набором команд, в которых сложно запутаться.
    Рассмотрим на примере задачу, решение которой и привело меня к этой утилите.
   Есть виртуальная машина с дисками С  и D. На ней стоит Hudson. По умолчанию он свои проекты складывает C:\Documents and Settings\<username>\.hudson. 



    Проект в svn по размеру огромный, поэтому при попытке его выкачать Hudson столкнулся с тем, что место на диске С закончилось. А на диске D места много. Самый простой способ в этой ситуации - создать символическую ссылку с  C:\Documents and Settings\<username>\.hudson.  например на  E:\hudson. Тогда все файлы будут доступны по старым ссылкам на диск С, но фактически они будут храниться ( и занимать место) на диске D. 
    Итак, наконец, последовательность действий:
1. Скачиваем Junction
2. Распаковываем архив в любую папку
3. Открываем cmd (Нажимаем Win+R, в открывшееся окно пишем cmd, нажимаем enter)
4. Копируем все файлы из "C:\Documents and Settings\<username>\.hudson" в "E:\hudson"
5. Удаляем "C:\Documents and Settings\<username>\.hudson"
6. Выполняем команду junсtion "C:\Documents and Settings\<username>\.hudson" "E:\hudson"

    Директория "C:\Documents and Settings\<username>\.hudsonсоздастся при успешном выполнении команды. 

   Если после запуска ошибок не появилось, то можно убедиться в успешности переноса перейдя в "C:\Documents and Settings\<username>\.hudson" и увидев там все файлы, находящиеся в исходной папке на диске D.

Чтобы удалить привязку выполняем команду junction -d "C:\Documents and Settings\<username>\.hudson".

    Какие могут возникнуть проблемы:
1. 'junction' is not recognized as an internal or external command,
operable program or batch file. - при возникновении такой ошибки нужно 
1.1. или открыв cmd перейти в папку с распакованным junction (выполнить cd <junctiondir>)
1.2. или при выполнении команды указывать полный путь до файла, например
"C:\Program Files\Junction\junction.exe" "C:\dir" "D:\dir"
2.  Error setting junction for c:\dir: The data present in the reparse point buffer is invalid. - эта ошибка происходит при неправильном указании пути - проверьте, что пути указаны правильно, а если они с пробелами, то в кавычках.

четверг, 6 февраля 2014 г.

Генерация JAXB-классов по xsd или xml

Иногда случаются ситуации, когда необходимо написать JAXB-классы для xml, а если повезло, то по xsd.
Есть, конечно, плагины для Eclipse и наверняка много других способов, но на мой взгляд проще всего поступить так.

1. Генерация JAXB из xml

Если в наличие есть только  xml, то придется сначала получить из него xsd. Это можно сделать вручную, конечно (особенно если файл не очень сложный), но быстрее файл схемы также сгенерировать. Неплохой онлайн-инструмент для генерации xsd  по  xml находится здесь:  http://www.freeformatter.com/xsd-generator.html

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

Получив, наконец, с помощью этого или любого другого инструмента xsd идем и выполняем действия, описанные в пункте 2

2. Генерация JAXB из xsd

Берем свой  xsd  файл (например, он называется  xsd.xsd ) и идем в директорию, куда установлена  Java. Примерно сюда: C:\Program Files\Java\jdk1.7.0_40\bin

Открываем там командную строку (например, зажимая шифт кликаем правой кнопкой и в открывшемся меню нажимаем что-нибудь похожее на Open command window here).

Далее выполняем несложную команду > xjc.exe xsd.xsd

В случае успеха в консоли увидим, что парсинг схемы и генерация классов прошли успешно.

 
Идем в директорию и забираем получившиеся файлы себе в проект. 

Ну и да, скорее всего, если вы попали на эту статью, то знаете, что такое JAXB, зачем он нужен и как его использовать. Но если вдруг что-то позабылось, то освежить память можно здесь:

Page Object генератор для Selenium тестов

Когда нужно автоматизировать тестирование приложения с большим количеством страниц, бывает довольно утомительно описывать их вручную.
Очень удобный, простой и бесплатный сервис доступен по ссылке:
http://whispering-retreat-7160.herokuapp.com/generator

Он может генерировать Selenium Page Objects по html коду или по ссылке на нужный ресурс.
Поддерживаемые генератором языки: Java, C#, PHP, Ruby.

Работает он так:
1. Копируете-вставляете html-код
2. Выбираете целевой язык: Java, C#, PHP или Ruby
3. Пишете нужные Вам селекторы через ";", например //a;//input
4. Нажимаете на кнопку Generate

5. На выходе получаете свой Page Object:
public class CustomPage {

 @FindBy(id="paramField")
 private WebElement paramField;

 @FindBy(id="code")
 private WebElement code;

 @FindBy(id="description")
 private WebElement description;

}

И все, копируете его себе, переименовываете и радуетесь жизни!

Автор активно работает над своим сервисом, скоро обещает генерировать и некоторые методы, а не только поля.