Статьи

Непрерывное тестирование с Selenium и JBehave с использованием объектов Page

С момента основания Майка мы всегда стремились максимально автоматизировать тестирование. В течение некоторого времени мы использовали Selenium для наших функциональных / приемочных испытаний, и до сих пор были очень довольны этим подходом. Первоначально мы решили использовать тесты в стиле Selenese , так как считали, что это позволит непрограммистам поддерживать и расширять охват наших тестов. Кто-то с базовым пониманием разметки и достаточной способностью вносить небольшие изменения в HTML-код, созданный в Selenium IDE, Тем не менее, по мере того, как спектр возможностей, предоставляемых нашей платформой, начал расти, мы обнаружили, что мы выполняем множество ctrl + c и ctrl + v из сценариев Selenese и в целом нарушаем наши принципы DRY. После некоторых внутренних дискуссий, мы , наконец , остановились на новом подходе, принимающее поведение Driven Development ( BDD ) метода. Это прекрасно работает с нашим гибким подходом к разработке на основе пользовательских историй и (как вы могли ожидать) нашими передовыми внутренними практиками при использовании непрерывной интеграции для наших собственных целей.

BDD Framework Выбор

Кодовой базой Майка в основном является Java, поэтому было разумно выбрать среду BDD на основе Java. Мы могли бы выбрать что-то вроде любимого огурца Ruby rockstars , который сейчас хорошо известен, но в конце концов остановился на JBehave . Он получил наш голос по ряду причин:

  • Это активный проект, с регулярными производственными выпусками.
  • Он «изобретен», и вы можете связать удобный плагин JBehave с соответствующими фазами жизненного цикла
  • Он предоставляет подкомпонент веб-тестирования, который дает вам красивую простую абстракцию для Selenium
  • Сценарии могут быть определены в виде простого текста, так же, как огурец
  • Он интегрируется в IDE, как и любая другая основанная на xUnit среда тестирования (щелкните правой кнопкой мыши> Run As> JUnit Test)

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

Пример

Я рассмотрю пример простого сценария в стиле BDD JBehave, который пытается протестировать эту вечную популярность — веб-приложение Java Petstore:

 Scenario: Successful Login

Given the user opens the home page
When the user clicks the enter store link
Then the store front page should be displayed
When the user clicks the sign in link
Then the store login page should be displayed
When the user enters username j2ee
And the user enters password j2ee
And the user clicks the login button
Then the store front page should be displayed for user ABC

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

Итак, теперь, когда у нас есть наш сценарий, сохраненный в текстовом файле с именем ‘login_scenarios’, с помощью JBehave нам нужно создать два дополнительных класса. Это:

  1. тривиальный подкласс org.jbehave.scenario.Scenario, имя которого отображается на связанный текстовый файл ( LoginScenarios.java )
  2. подкласс org.jbehave.web.selenium.SeleniumSteps ( LoginSteps.java ), который обеспечивает реализацию для каждого из операторов «Given», «When» и «Then».

Например:

 @Given("the user opens the home page")
public void theUserOpensTheHomePage(){
homePage = new HomePage(selenium, runner);
homePage.open("/jpetstore");
}

Обратите внимание, как JBehave использует простые аннотации для сопоставления элементов сценария с методами Java. Вы, вероятно, также заметите использование объекта «page» в теле метода, который выполняет тяжелую работу тестов. Кроме того, методы в предоставляемом JBehave базовом классе SeleniumSteps могут быть переопределены при необходимости. Например, переопределите createSelenium (), если вам нужно предоставить пользовательский экземпляр Selenium с альтернативной конфигурацией.

Объекты страницы

В пользовательском интерфейсе веб-приложения есть области, с которыми взаимодействуют наши тесты. Использование шаблона Page Object позволяет нам интуитивно моделировать эти страницы как объекты в тестовом коде. Это значительно уменьшает объем дублирующегося кода и означает, что в случае изменения пользовательского интерфейса исправления необходимо применять только в одном месте. Это означает, что мы вернем наше СУХОЕ тестирование моджо после нашего опыта с размеченной копией и разметкой Selenese. Чтобы упростить ситуацию, рекомендуется создать абстрактный базовый класс ( Page.java ), который предоставляет ряд конкретных методов своим конкретным дочерним элементам . Вот пример класса, который представляет страницу входа в наше демонстрационное приложение Java petstore.

public class StoreLoginPage extends Page {

public StoreLoginPage(Selenium selenium, ConditionRunner runner) {
super(selenium, runner);
}

@Override
public void verifyPage() {
textIsVisible("Please enter your username and password.");
}

public void verifyPresenceOfInvalidCredentialsErrorMessage(){
textIsVisible("Invalid username or password. Signon failed.");
}

public void typeUsername(String username){
type("//input[@name='username']", username);
}

public void typePassword(String password){
type("//input[@name='password']", password);
}

public StoreFrontPage clickLoginButton(){
clickButton("//input[@value='Login']");
waitForPageToLoad();
return new StoreFrontPage(selenium, runner);
}
}

Как только эти классы страниц подключены к нашим подклассам SeleniumSteps, мы можем использовать методы действия (открыть, щелкнуть, ввести и т. Д.) Или стиль проверки для запуска тестов.

Maven Magic

Как упоминалось ранее, мы выбрали JBehave частично из-за его интеграции с Maven. Существует плагин, который вы можете настроить для выполнения тестов на необходимом этапе:

<project>
[...]
<plugins>
[...]
<plugin>
<groupId>org.jbehave</groupId>
<artifactId>jbehave-maven-plugin</artifactId>
<version>2.5.1</version>
<executions>
<execution>
<id>run-scenarios-found</id>
<phase>integration-test</phase>
<configuration>
<scenarioClassNames>
<scenarioClassName>
com.mikeci.jpetstore.test.scenario.LoginScenarios
</scenarioClassName>
</scenarioClassNames>
<classLoaderInjected>false</classLoaderInjected>
<skip>false</skip>
<ignoreFailure>false</ignoreFailure>
<batch>true</batch>
<scope>test</scope>
</configuration>
<goals>
<goal>run-scenarios</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.jbehave.web</groupId>
<artifactId>jbehave-web-selenium</artifactId>
<version>2.1.4</version>
</dependency>
</dependencies>
</plugin>
[...]
</plugins>
[...]
</project>

Очевидно, что при выполнении этих сценариев нам нужны некоторые дополнительные сервисы — приложение должно быть развернуто и доступно вместе с работающим сервером selenium. Например, в зоомагазине для этих целей используются плагины Maven Cargo и Selen. Взгляните на полный неэкспонированный файл pom.xml, чтобы увидеть, как они настроены.

Запуск примера

Предварительными условиями являются клиент Subversion, Maven 2.2.x, Java 1.6.x и Firefox. Локальные порты 8080 и 4444 также должны быть свободны.

Проверьте проект:

~$ svn co https://mikesamples.googlecode.com/svn/trunk/maven/jpetstore-maven-multi-module/ jpetstore
~$ cd jpetstore

Запустите сборку Maven:

~$ mvn clean install -Pmikeci,run-functional-tests,run-on-desktop

В общем, это должно создать веб-приложение JPetstore, развернуть его на Jetty, запустить Selenium и запустить два сценария JBehave. Вы можете использовать этот пример для начальной загрузки своей собственной реализации JBehave / Selenium и быстро начать работу с BDD.