v2.22.0
=======
Project:
* Code grant from Google acknowledged in our copyright
headers. Thanks, Google!
WebDriver:
* JRE dependency upped to Java 6.
* IE driver now uses the IEDriverServer. You may need to download
this. Set the "useLegacyInternalServer" to boolean true if you
need the old behaviour.
* Standardized colour values returned from getCssValue are
normalized to RGBA.
* IE can use synthesized events if the capability
"enableNativeEvents" is set to false. This is experimental and not
expected to work properly.
* Native events added for Firefox 12.
* Native events retained for Firefox 10, 11, and 3.x
* Selenium-backed WebDriver can now return WebElements from
executeScript.
* With WebElement.getAttribute() a boolean attribute will return
"null" if not present on an element.
* A NoSuchWindowException will be thrown if the currently selected
window is closed and another command is sent.
* SafariDriver improved: frame switching, snapshot taking and JS
executing added.
* SafariDriver: changed message protocol. The 2.22.0 SafariDriver will
not be backwards compatible with Selenium 2.21.
* FIXED: 185: Appending screenshots to remote exceptions is now
optional. Controlled via the "webdriver.remote.quietExceptions"
capability.
* FIXED: 1089: Style attributes are no longer lower-cased by default.
* FIXED: 1934: Firefox cleans up temporary directories more effectively.
* FIXED: 3647: WebElement.sendKeys now works in Firefox on XHTML pages.
* FIXED: 3758: Maximize windows from inside a frame works as expected.
* FIXED: 3825: Alerts from a nested iframe are now handled properly.
Grid:
* Fixing Firefox profile extraction if a grid node started from a
network location (UNC path)
Atoms:
* bot.actions.type now works as expected in Firefox 12.
* Introduced better mouse and keyboard abstractions
пятница, 1 июня 2012 г.
Релиз 2.22
вторник, 22 мая 2012 г.
BDD и Selenium
В данной статье пойдет речь о BDD и его применении к тестированию веб-приложений.
Ну и естественно не обойдется без нашего любимого Selenium.
Надеюсь все что тут написано не вызовет вопросов )))))))) Мы используем аннотации взятые из библиотеки jbehave и говорим с какими фразами из файла .story они должны совпадать.
Слова со знаком $ это переменные, имя переменной должно совпадать с именем параметра в аннотированном методе.
Теперь самое интересное:
Каким способом это все запустить ???????????????????
Для этого напишем еще один класс BehaveExample (название не случайное ).
public class BehaveExample extends JUnitStory {
@Override
public Configuration configuration() {
return new MostUsefulConfiguration()
// Ишем истории в Classpath
.useStoryLoader(new LoadFromClasspath(this.getClass()))
// Вывод в консоль и текстовый файл
.useStoryReporterBuilder(new StoryReporterBuilder().withDefaultFormats().withFormats(Format.CONSOLE, Format.TXT));
}
// Тут опишем наши классы с описанием шагов
@Override
public InjectableStepsFactory stepsFactory() {
return new InstanceStepsFactory(configuration(), new BehaveTests());
}
}
для запуска уже почти все готово. Теперь положим наш файл истории рядом с файлом BehaveExample.java. Запустим BehaveExample.java как JUnit тест.
Вуаля )))) Открылся браузер, зашел на гугл, проверил заголовок и закрылся, как раз так как мы и описывали !!!!!!!
Ну и естественно не обойдется без нашего любимого Selenium.
ЧАСТЬ ПЕРВАЯ
Что такое BDD ? Если в двух словах BDD это подход к тестированию и разработке с использованием пользовательских сценариев, как основы для тестов. Данный подход призван сократить расстояние между аналитиками, разработчиками и тестировщиками.
Мы будем рассматривать библиотеку JBehave.
Как выглядит сценарий тестирования на JBehave ? Это файл с расширением .story и примерно следующего содержания:
Scenario: trader is not alerted below thresholdGiven a stock of symbol STK1 and a threshold of 10.0When the stock is traded at 5.0Then the alert status should be OFFScenario: trader is alerted above thresholdGiven a stock of symbol STK1 and a threshold of 10.0When the stock is traded at 11.0Then the alert status should be ON
Судя по виду не сложно. Сценарии в таком виде позволяют описывать use-кейсы вполне человеческим языком.
Все предложения в файле должны начинаться со слов Given Then и When.
Предположим мы решили написать для примера небольшую историю для проверки открытия сайта и проверки его заголовка.
Напишем что-то вроде
Given site http://www.google.com
When title is Google
Then close
When title is Google
Then close
и сохраним как behave_example.story
История использования у нас уже есть, теперь перейдем к реализации кода, который скажет браузеру что с этой историей делать.
ЧАСТЬ ВТОРАЯ
Создадим в Eclipse maven-проект. Назовем его JBehaveProj. (не будем цепляться к названию, это только для примера).
В pom.xml в секции dependency запишем следующее
<dependencies>
<dependency>
<groupId>org.jbehave</groupId>
<artifactId>jbehave-core</artifactId>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.jbehave</groupId>
<artifactId>jbehave-core</artifactId>
<version>3.6.2</version>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>2.21.0</version>
</dependency>
</dependencies>
</dependencyManagement>
<dependency>
<groupId>org.jbehave</groupId>
<artifactId>jbehave-core</artifactId>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.jbehave</groupId>
<artifactId>jbehave-core</artifactId>
<version>3.6.2</version>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>2.21.0</version>
</dependency>
</dependencies>
</dependencyManagement>
Теперь maven подгрузит нам две библиотеки jbehave-core и selenium-java. Обе они нам понадобятся.
Теперь когда наш проект настроен напишем код.
Создадим класс BehaveTests , этот класс будет содержать имплементацию того что написано в файле .story.
public class BehaveTests {
FirefoxDriver driver = new FirefoxDriver();
@Given("site $url")
public void open(String url){
driver.get(url);
}
@When("title is $title")
public void find(String title ){
if (driver.getTitle().equals(title)){
System.out.println("Совпало");
}
else{
System.out.println("Не совпало");
}
}
@Then("close")
public void close(){
driver.close();
}
Создадим класс BehaveTests , этот класс будет содержать имплементацию того что написано в файле .story.
public class BehaveTests {
FirefoxDriver driver = new FirefoxDriver();
@Given("site $url")
public void open(String url){
driver.get(url);
}
@When("title is $title")
public void find(String title ){
if (driver.getTitle().equals(title)){
System.out.println("Совпало");
}
else{
System.out.println("Не совпало");
}
}
@Then("close")
public void close(){
driver.close();
}
Надеюсь все что тут написано не вызовет вопросов )))))))) Мы используем аннотации взятые из библиотеки jbehave и говорим с какими фразами из файла .story они должны совпадать.
Слова со знаком $ это переменные, имя переменной должно совпадать с именем параметра в аннотированном методе.
Теперь самое интересное:
Каким способом это все запустить ???????????????????
Для этого напишем еще один класс BehaveExample (название не случайное ).
public class BehaveExample extends JUnitStory {
@Override
public Configuration configuration() {
return new MostUsefulConfiguration()
// Ишем истории в Classpath
.useStoryLoader(new LoadFromClasspath(this.getClass()))
// Вывод в консоль и текстовый файл
.useStoryReporterBuilder(new StoryReporterBuilder().withDefaultFormats().withFormats(Format.CONSOLE, Format.TXT));
}
// Тут опишем наши классы с описанием шагов
@Override
public InjectableStepsFactory stepsFactory() {
return new InstanceStepsFactory(configuration(), new BehaveTests());
}
}
для запуска уже почти все готово. Теперь положим наш файл истории рядом с файлом BehaveExample.java. Запустим BehaveExample.java как JUnit тест.
Вуаля )))) Открылся браузер, зашел на гугл, проверил заголовок и закрылся, как раз так как мы и описывали !!!!!!!
вторник, 15 мая 2012 г.
Maven configuration for Java 6
Многие начинающие пользователи maven сталкивались с проблемой что проект в ide собирается, а при сборке из командной строки начинает ругаться на версию Java.
Чаще всего такое поведение вызвано использованием в вашем коде штучек из Java 5,6,7.
Для решения этой проблемы в pom.xml нужно добавить следующие записи:
<properties>
<java.version>1.5</java.version>
</properties>
И добавить следующие строки в секцию <build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
</plugins>
после добавления этих записей все начнет собираться из командной строки без ошибок.
Чаще всего такое поведение вызвано использованием в вашем коде штучек из Java 5,6,7.
Для решения этой проблемы в pom.xml нужно добавить следующие записи:
<properties>
<java.version>1.5</java.version>
</properties>
И добавить следующие строки в секцию <build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
</plugins>
после добавления этих записей все начнет собираться из командной строки без ошибок.
четверг, 10 мая 2012 г.
CSS и XPath
В таблице ниже вы можете увидеть соответствие между xpath запросом и его аналогом в css.
| CSS селектор | XPath запрос | Описание |
|---|---|---|
| * | //* | Любой элемент |
| E | //E | Элемент с тэгом E (типа E) |
| E[foo] | //E[@foo] | Элемент E, у которого есть атрибут foo |
| E[foo="bar"] | //E[@foo="bar"] | Элемент E, у которого значение атрибута foo равно bar |
| E[foo~="bar"] | //E[contains( concat(" ", @foo, " "), concat(" ", "bar", " ") )] | Элемент E, у которого значение атрибута foo представляет собой список значений, разделенных пробелами, и одно из них равно bar |
| E[foo^="bar"] | //E[starts-with(@foo, "bar")] | Элемент E, у которого значение атрибута foo начинается с bar |
| E[foo$="bar"] | //E[substring(@foo, string-length(@foo) - string-length("bar") + 1) = "bar"] | Элемент E, у которого значение атрибута foo заканчивается bar |
| E[foo*="bar"] | //E[contains(@foo, "bar")] | Элемент E, у которого значение атрибута foo содержит bar |
| E[foo|="bar"] | //E[@foo="bar" or starts-with(@foo, concat("bar", "-")] | Элемент E, у которого значение атрибута foo представляет собой разделенный дефисами список значений, который начинается с bar |
| E:nth-child(a*n+b) | a < 0: //*[position() <= b][name() = "E"] a == 0: //*[position() = b][name() = "E"] a > 0: //*[(position() + b) mod a = 0][name() = "E"] |
Элемент E, который является a*n+b ребенком своего родителя |
| E:nth-last-child(a*n+b) | a < 0: //*[position() > last() — b][name() = "E"] a == 0: //*[last() - b][name() = "E"] a > 0: //*[(last() - position() + b - 1) mod a = 0][name() = "E"] |
Элемент E, который является a*n+b ребенком с конца своего родителя |
| E:first-child | //*/*[1][name() = "E"] или //*/*[1]/self::E |
Элемент E, который является первым ребенком своего родителя |
| E:last-child | //*/*[last()][name() = "E"] или //*/*[last()]/self::E |
Элемент E, который является последним ребенком своего родителя |
| E:only-child | //*[count(*) = 1]/E | Элемент E, который является единственным ребенком своего родителя |
| E:empty | //E[count(*) = 0 and (not(text()) or text() = "")] | Элемент E, у которого нет детей, включая текстовых нод |
| E:checked | //E[@checked] | - |
| E:enabled | //E[@disabled="false"] | - |
| E:disabled | //E[@disabled="true"] | - |
| E.warning | //E[contains(concat(" ", @class, " "), concat(" ", "warning", " ")] | Элемент E, у которого есть класс warning |
| #myid | id(«myid») | Элемент c id равным myid |
| E#myid | //E[@id="myid"] | Элемент E, у которого id равен myid |
| E:not(s) | //E[not(_selector_)] | Отрицательный селектор |
| E F | //E//F | Элемент F, который является потомков E |
| E > F | //E/F | Элемент F, который является ребенком E |
| E + F | //E/following-sibling::*[1]/self::F | Элемент F, который непосредственно следует за E |
| E ~ F | //E/following-sibling::F | Элемент F, который следует за E |
четверг, 3 мая 2012 г.
Учим Properties понимать русский язык
В ходе проекта передо мной возникла необходимость подгружать некоторые значения из файлов. Наиболее простым и быстрым решением показалось считывать эти файлы как объекты Properties.
Но вылезла неприятная особенность, метод Properties.load() по умолчанию загружает все данные в кодировке ISO-8859-1. Это не есть хорошо так как файлы должны содержать кирилицу и после загрузки таким макаром она превращалась в набор кракозябр.
Решение оказалось довольно таки очевидным:
Properties props=new Properties();
props.load(new InputStreamReader(new FileInputStream("system.props"), "UTF-8"));
При загрузке таким образом кириллица остается кириллицей ))
Но вылезла неприятная особенность, метод Properties.load() по умолчанию загружает все данные в кодировке ISO-8859-1. Это не есть хорошо так как файлы должны содержать кирилицу и после загрузки таким макаром она превращалась в набор кракозябр.
Решение оказалось довольно таки очевидным:
Properties props=new Properties();
props.load(new InputStreamReader(new FileInputStream("system.props"), "UTF-8"));
При загрузке таким образом кириллица остается кириллицей ))
Подписаться на:
Сообщения (Atom)