Инструмент автоматизации функционального тестирование веб-интерфейсов 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. Подробно описан в оф. документации.