Serenity BDD и сценарий

Serenity BDD и сценарий

1. обзор

В этой статье мы кратко рассмотрим шаблон сценария в Serenity BDD. Мы предлагаем вам сначала прочитатьbasics of Serenity BDD, прежде чем читать этот. Также может быть интересна статья оSerenity BDD integration with Spring.

Сценарий, представленный в Serenity BDD, направлен на поощрение хороших навыков тестирования и хорошо разработанных наборов тестов, позволяя командам писать более надежные и надежные тесты. Он основан на Selenium WebDriver и модели Page Objects. Если вы читали нашиintroduction to Selenium, то эти концепции вам будут знакомы.

2. Maven Dependency

Во-первых, давайте добавим в файлpom.xml следующие зависимости:


    net.serenity-bdd
    serenity-junit
    1.4.0


    net.serenity-bdd
    serenity-screenplay
    1.4.0


    net.serenity-bdd
    serenity-screenplay-webdriver
    1.4.0

Последние версииserenity-screenplay иserenity-screenplay-webdriver можно загрузить из центрального репозитория Maven.

Нам также нужны веб-драйверы для выполнения сценария - подойдет либоChromeDriver, либоMozilla-GeckoDriver. В этой статье мы будем использовать ChromeDriver.

Для включения WebDriver требуется следующая конфигурация плагина, в которой значениеwebdriver.chrome.driver должно быть относительным путем к двоичному файлу ChromeDriver в нашем проекте maven:


    maven-failsafe-plugin
    2.20
    
        
            chromedriver
        
    

3. Поддержка WebDriver

Мы можем заставить Serenity управлять экземпляром WebDriver, отметив аннотацию@Managed в переменной WebDriver. Serenity откроет соответствующий драйвер в начале каждого теста и закроет его по окончании теста.

В следующем примере мы запускаем ChromeDriver и открываем Google для поиска "example". Мы ожидаем, что имя Евгения будет присутствовать в результатах поиска:

@RunWith(SerenityRunner.class)
public class GoogleSearchLiveTest {

    @Managed(driver = "chrome")
    private WebDriver browser;

    @Test
    public void whenGoogleexampleThenShouldSeeEugen() {
        browser.get("https://www.google.com/ncr");

        browser
          .findElement(By.name("q"))
          .sendKeys("example", Keys.ENTER);

        new WebDriverWait(browser, 5)https://www.example.com/serenity-screenplay
          .until(visibilityOfElementLocated(By.cssSelector("._ksh")));

        assertThat(browser
          .findElement(By.cssSelector("._ksh"))
          .getText(), containsString("Eugen (example)"));
    }
}

Если мы не укажем никаких параметров для@Managed, Serenity BDD будет использовать Firefox в этом случае. Весь список поддерживаемых драйверов помечен аннотацией@Managed:firefox, chrome, iexplorer, htmlunit, phantomjs.

Если нам нужно протестировать в IExplorer или Edge, мы можем загрузить веб-драйверы изhere(for IE) иhere(for Edge) соответственно. Safari WebDriver доступен только в MacOS под/usr/bin/safaridriver.

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

Объекты Serenity Page представляют объект страницы WebDriver. PageObject скрывает детали WebDriver для повторного использования.

4.1. Пример рефакторинга с использованиемPageObject

Давайте уточним наш предыдущий тест, используя сначалаPageObject, извлекая действия по поиску, поиску и проверке результатов:

@DefaultUrl("https://www.google.com/ncr")
public class GoogleSearchPageObject extends PageObject {

    @FindBy(name = "q")
    private WebElement search;

    @FindBy(css = "._ksh")
    private WebElement result;

    public void searchFor(String keyword) {
        search.sendKeys(keyword, Keys.ENTER);
    }

    public void resultMatches(String expected) {
        assertThat(result.getText(), containsString(expected));
    }
}

WebElement представляет собой элемент HTML. Мы можем взаимодействовать с веб-страницами через API интерфейса. В приведенном выше примере мы использовали два способа поиска веб-элементов на странице: по имени элемента и по классам CSS элемента.

Существует больше подходов к применению при поиске веб-элементов, таких как поиск по имени тега, поиск по тексту ссылки и т. Д. Обратитесь к нашемуguide to Selenium для получения более подробной информации.

Мы также можем заменитьWebElement наWebElementFacade, что обеспечивает более плавные API для работы с веб-элементами.

КакSerenity will automatically instantiate any PageObject fields in the JUnit test, предыдущий тест можно переписать в более чистый:

@RunWith(SerenityRunner.class)
public class GoogleSearchPageObjectLiveTest {

    @Managed(driver = "chrome")
    private WebDriver browser;

    GoogleSearchPageObject googleSearch;

    @Test
    public void whenGoogleexampleThenShouldSeeEugen() {
        googleSearch.open();

        googleSearch.searchFor("example");

        googleSearch.resultMatches("Eugen (example)");
    }
}

Теперь мы можем выполнять поиск по другим ключевым словам и сопоставлять результаты поиска, не внося никаких изменений вGoogleSearchPageObject.

4.2. Асинхронная поддержка

В настоящее время многие веб-страницы обслуживаются или отображаются динамически. Чтобы справиться с такими случаями,PageObject также поддерживает множество разнообразных функций, которые позволяют нам проверять статусы элементов. We can check if the elements are visible, or wait until they are visible before proceeding.

Давайте усовершенствуем методresultMatches, убедившись, что элемент, который мы хотим видеть, является видимым:

public void resultMatches(String expected) {
    waitFor(result).waitUntilVisible();
    assertThat(result.getText(), containsString(expected));
}

Если мы не ожидаем слишком долгого ожидания, мы можем явно указать тайм-аут для ожидающих действий:

public void resultMatches(String expected) {
    withTimeoutOf(5, SECONDS)
      .waitFor(result)
      .waitUntilVisible();
    assertThat(result.getText(), containsString(expected));
}

5. Шаблон сценария

Шаблон сценария применяет принципы проектирования SOLID для автоматического приемочного тестирования. Общее понимание паттерна сценария можно объяснить в контекстеgiven_when_then следующим образом:

  • given -Actor, способный выполнять несколькоTask

  • when -Actor выполняетTask

  • then –Actor должен увидеть эффект и проверить результаты

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

Сначала определите задачи, которые Китти может выполнять.

  1. Китти может использовать Google:

    public class StartWith implements Task {
    
        public static StartWith googleSearchPage() {
            return instrumented(StartWith.class);
        }
    
        GoogleSearchPage googleSearchPage;
    
        @Step("{0} starts a google search")
        public  void performAs(T t) {
            t.attemptsTo(Open
              .browserOn()
              .the(googleSearchPage));
        }
    }
  2. Китти может сделать поиск в Google:

    public class SearchForKeyword implements Task {
    
        @Step("{0} searches for '#keyword'")
        public  void performAs(T actor) {
            actor.attemptsTo(Enter
              .theValue(keyword)
              .into(GoogleSearchPage.SEARCH_INPUT_BOX)
              .thenHit(Keys.RETURN));
        }
    
        private String keyword;
    
        public SearchForKeyword(String keyword) {
            this.keyword = keyword;
        }
    
        public static Task of(String keyword) {
            return Instrumented
              .instanceOf(SearchForKeyword.class)
              .withProperties(keyword);
        }
    }
  3. Китти может видеть результаты поиска Google:

    public class GoogleSearchResults implements Question> {
    
        public static Question> displayed() {
            return new GoogleSearchResults();
        }
    
        public List answeredBy(Actor actor) {
            return Text
              .of(GoogleSearchPage.SEARCH_RESULT_TITLES)
              .viewedBy(actor)
              .asList();
        }
    }

Также мы уже определили поиск GooglePageObject:

@DefaultUrl("https://www.google.com/ncr")
public class GoogleSearchPage extends PageObject {

    public static final Target SEARCH_RESULT_TITLES = Target
      .the("search results")
      .locatedBy("._ksh");

    public static final Target SEARCH_INPUT_BOX = Target
      .the("search input box")
      .locatedBy("#lst-ib");
}

Теперь наш основной тестовый класс будет выглядеть так:

@RunWith(SerenityRunner.class)
public class GoogleSearchScreenplayLiveTest {

    @Managed(driver = "chrome")
    WebDriver browser;

    Actor kitty = Actor.named("kitty");

    @Before
    public void setup() {
        kitty.can(BrowseTheWeb.with(browser));
    }

    @Test
    public void whenGoogleexampleThenShouldSeeEugen() {
        givenThat(kitty).wasAbleTo(StartWith.googleSearchPage());

        when(kitty).attemptsTo(SearchForKeyword.of("example"));

        then(kitty).should(seeThat(GoogleSearchResults.displayed(),
          hasItem(containsString("Eugen (example)"))));
    }
}

После выполнения этого теста мы увидим скриншоты каждого шага, который Китти выполнила в отчете об испытаниях:

image

6. Резюме

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

Дополнительные сведения оPageObject и шаблоне сценария в Serenity BDD см. В соответствующем разделе документации Serenity.

Как всегда, полный пример кода можно найти вon the Github.