Инструмент автоматизации функционального тестирование веб-интерфейсов Selenium 2 включает в себя два продукта: Selenium Remote Control (Selenium 1) и Webdriver.
Отличаются RC и Webdriver тем, что RC взаимодействует с браузером с помощью Selenium Core — специального инструмента, который может работать с любым браузером через JavaScript. Webdriver же использует нативный интерфейс, что позволяет более точно повторять действия пользователя, однако для взаимодействия с каждым отдельным браузером нужен специальный драйвер (т.к. у каждого браузера свой собственный нативный интерфейс), но при этом скорость прохождения теста повышается. На данный момент существуют такие драйвера:
Использование нативного интерфейса также причиняет набольшое неудобство — любое нажатие клавиши в процессе прохождения может «обрушить» тест.
Как преимуществом, так и недостатком Selenium RC есть использование Selenium Server Standalone. С одной стороны использование сервера упрощает логирование результатов, что существенно упрощает написание автотестов(на Webdriver приходится ставить различные «костыли», чтобы выяснить где именно произошла ошибка потому, как из-за скорости прохождения тестов это не всегда можно определить визуально), но с другой стороны — увеличивается время прохождения теста и невозможность использовать для тестирования страниц на мобильном устройстве.
Недостатком Webdriver по сравнению с класическим RC есть сложность имитирования действий как, например, наведение курсора мыши. С другой стороны Webdriver как и реальный пользователь не может работать со скрытыми элементами или, например, не сможет ввести текст в поле, полностью перекрытое другим элементом.
Отдельно стоит сказать о работе с JavaScript и AJAX. В Webdriver реализованы механизма ожидания завершения AJAX-запросов: Explicit Waits (явные ожидания) и Implicit Waits (неявные ожидания) (Подробнее здесь Ожидания в Webdriver). В RC для ожидания AJAX приходится использовать средства языка программирования. Также стоит отметить, что Remote Control не всегда корректно работает с JS. Например, selenium.click не может вызвать JS-ивент onMouseDown и приходится гадать, «что же там использовал разработчик?» чтобы написать корректную команду. С Webdriver подобные проблеммы не возникают.
В Selenium Remote Control в процессе развития сформировался достаточно широкий набор комманд, в то время как в Webdriver почти всё сводится к .click или .sendKeys (вобшем-то реальный пользователь может сделать не намного больше, однако, например, простая комманда для снятия скриншота или выбора Ok/Cancel в диалоговом окне не помешала бы). Однако в Webdriver реализовано большее количество локаторов для поиска элемента на странице.
By.id — обращается к элементу по ID;
By.name — обращается по имени элемента name:
By.xpath — обращается к элементу по xpath выражению;
By.tagName — поиск по имени HTML тэга;
By.cssSelector — данный тип локаторов основан на описаниях таблиц стилей (CSS);
By.className — поиск по CSS классу элемента;
By.linkTex — поиск ссылки по тексту;
By.partionalLinkText — поиск ссылки по части текста;
Рассмотрим примеры тестов на RC и Webdriver (Java).
Напишем автотесты, которые заходят на Google, вводят в строку поиска zerg rush, нажимают кнопку поиска, затем после небольшего ожидания снимают скриншот окна.
Remote Control:
Webdriver
Из всего выше сказанного видно, что и Remote Control и Webdriver имеют как недостатки так и преимущества. В большом количестве случаев удобнее использовать RC, т.к. большой набор комманд и возможность работать со скрытыми элементами, а также возможность получать логи сервера существенно упрошают и ускоряют (время — деньги) процесс написания и последующего адаптирования тестов. Webdriver же уместно использовать там, где не справляется (плохо справляется) RC, например для перегруженых AJAX-запросами веб интерфейсов или в местах где крайне вожно точно симитировать действия пользователя (следует заметить, что Webdriver и был внедрён потому, что с появлением более новых веб-технологий Selenium RC просто исчерпал себя и необходимость в альтернативном подходе стала очевидной).
Также в Selenium 2 реализована возможность перехода с RC на Webdriver. Подробно описан в оф. документации.
Отличаются RC и Webdriver тем, что RC взаимодействует с браузером с помощью Selenium Core — специального инструмента, который может работать с любым браузером через JavaScript. Webdriver же использует нативный интерфейс, что позволяет более точно повторять действия пользователя, однако для взаимодействия с каждым отдельным браузером нужен специальный драйвер (т.к. у каждого браузера свой собственный нативный интерфейс), но при этом скорость прохождения теста повышается. На данный момент существуют такие драйвера:
- HtmlUnitDriver — универсальный драйвер, не требующий установки браузера;
- FirefoxDriver — драйвер для Firefox;
- InternetExplorerDriver — драйвер для IE;
- ChromeDriver — драйвер для Google Chrome;
- OperaDriver — драйвер для Opera;
- SafariDriver — драйвер для Safari;
- AndriodDriver — драйвер для мобильного браузера на Android;
- IphoneDriver — драйвер для мобильного браузера на iPhone;
Использование нативного интерфейса также причиняет набольшое неудобство — любое нажатие клавиши в процессе прохождения может «обрушить» тест.
Как преимуществом, так и недостатком Selenium RC есть использование Selenium Server Standalone. С одной стороны использование сервера упрощает логирование результатов, что существенно упрощает написание автотестов(на Webdriver приходится ставить различные «костыли», чтобы выяснить где именно произошла ошибка потому, как из-за скорости прохождения тестов это не всегда можно определить визуально), но с другой стороны — увеличивается время прохождения теста и невозможность использовать для тестирования страниц на мобильном устройстве.
Недостатком Webdriver по сравнению с класическим RC есть сложность имитирования действий как, например, наведение курсора мыши. С другой стороны Webdriver как и реальный пользователь не может работать со скрытыми элементами или, например, не сможет ввести текст в поле, полностью перекрытое другим элементом.
Отдельно стоит сказать о работе с JavaScript и AJAX. В Webdriver реализованы механизма ожидания завершения AJAX-запросов: Explicit Waits (явные ожидания) и Implicit Waits (неявные ожидания) (Подробнее здесь Ожидания в Webdriver). В RC для ожидания AJAX приходится использовать средства языка программирования. Также стоит отметить, что Remote Control не всегда корректно работает с JS. Например, selenium.click не может вызвать JS-ивент onMouseDown и приходится гадать, «что же там использовал разработчик?» чтобы написать корректную команду. С Webdriver подобные проблеммы не возникают.
В Selenium Remote Control в процессе развития сформировался достаточно широкий набор комманд, в то время как в Webdriver почти всё сводится к .click или .sendKeys (вобшем-то реальный пользователь может сделать не намного больше, однако, например, простая комманда для снятия скриншота или выбора Ok/Cancel в диалоговом окне не помешала бы). Однако в Webdriver реализовано большее количество локаторов для поиска элемента на странице.
By.id — обращается к элементу по ID;
By.name — обращается по имени элемента name:
By.xpath — обращается к элементу по xpath выражению;
By.tagName — поиск по имени HTML тэга;
By.cssSelector — данный тип локаторов основан на описаниях таблиц стилей (CSS);
By.className — поиск по CSS классу элемента;
By.linkTex — поиск ссылки по тексту;
By.partionalLinkText — поиск ссылки по части текста;
Рассмотрим примеры тестов на RC и Webdriver (Java).
Напишем автотесты, которые заходят на Google, вводят в строку поиска zerg rush, нажимают кнопку поиска, затем после небольшего ожидания снимают скриншот окна.
Remote Control:
import org.openqa.selenium.Keys; import com.thoughtworks.selenium.SeleneseTestCase; import java.util.concurrent.TimeUnit; import java.awt.event.KeyEvent; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.io.Writer; public class FirstTest extends SeleneseTestCase { public void setUp() throws Exception { setUp("http://google.com", "*firefox"); } public void testGoogle() throws Exception { File file = new File("путь куда сохрянять лог сервера"); if (file.exists()) { file.delete(); } selenium.open("/"); //переход на сайт Google selenium.windowMaximize(); //разворачиваем окно на весь экран selenium.waitForPageToLoad("30000"); //ожидание загрузки страницы selenium.type("name=q", "zerg rush"); //ввод текста в строку поиска selenium.click("name=btnG"); //нажатие кнопки поиска TimeUnit.SECONDS.sleep(5); //задержка 5 секунд selenium.captureEntirePageScreenshot("путь куда сохрянять скриншоты", ""); Writer output = new BufferedWriter(new FileWriter(file)); output.write(selenium.getLog()); output.close(); System.out.println("Test Complete"); //сообщение о завершении теста } }
Webdriver
import java.util.regex.Pattern; import java.util.concurrent.TimeUnit; import org.junit.*; import static org.junit.Assert.*; import static org.hamcrest.CoreMatchers.*; import org.openqa.selenium.*; import org.openqa.selenium.firefox.FirefoxDriver; import org.openqa.selenium.support.ui.Select; import java.awt.event.KeyEvent; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.io.Writer; import org.apache.commons.io.FileUtils; public class First_test { private WebDriver driver; private String baseUrl; private StringBuffer verificationErrors = new StringBuffer(); @Before public void setUp() throws Exception { driver = new FirefoxDriver(); baseUrl = "http://google.com"; driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS); //установка длительности таймаутов } @Test public void testGoogle() throws Exception { driver.get(baseUrl + "/"); //переход на сайт Google. ссылка забита в переменную baseUrl driver.findElement(By.name("q")).sendKeys("zerg rush"); //ввод текста в строку поиска driver.findElement(By.name("btnG")).click(); //нажатие кнопки поиска TimeUnit.SECONDS.sleep(5); //задержка 5 секунд File file = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE); String path = "путь куда сохрянять скриншоты"; FileUtils.copyFile(file, new File(path)); System.out.println("Test Complete"); //сообщение о завершении теста } @After public void tearDown() throws Exception { driver.quit(); String verificationErrorString = verificationErrors.toString(); if (!"".equals(verificationErrorString)) { fail(verificationErrorString); } } private boolean isElementPresent(By by) { try { driver.findElement(by); return true; } catch (NoSuchElementException e) { return false } } }
Из всего выше сказанного видно, что и Remote Control и Webdriver имеют как недостатки так и преимущества. В большом количестве случаев удобнее использовать RC, т.к. большой набор комманд и возможность работать со скрытыми элементами, а также возможность получать логи сервера существенно упрошают и ускоряют (время — деньги) процесс написания и последующего адаптирования тестов. Webdriver же уместно использовать там, где не справляется (плохо справляется) RC, например для перегруженых AJAX-запросами веб интерфейсов или в местах где крайне вожно точно симитировать действия пользователя (следует заметить, что Webdriver и был внедрён потому, что с появлением более новых веб-технологий Selenium RC просто исчерпал себя и необходимость в альтернативном подходе стала очевидной).
Также в Selenium 2 реализована возможность перехода с RC на Webdriver. Подробно описан в оф. документации.