SlideShare a Scribd company logo
1 of 104
Download to read offline
HtmlElements
PageObjects
Steps

PageObjects
Tests

 Steps

PageObjects
Рецепт приготовления
Вкусных тестов
PageObjects
public class SearchPage {
    @FindBy(id = "text")
    private WebElement requestInput;

    @FindBy(xpath = "//input[@type='submit']")
    private WebElement searchButton;

    @FindBy(name = "login")
    private WebElement loginInput;

    @FindBy(name = "passwd")
    private WebElement passwordInput;

    @FindBy(name = "b-form-button__input")
    private WebElement authorizeButton;

    public SearchPage(WebDriver driver) {
        PageFactory.initElements(driver, this);
    }

    public void searchFor(String request) {
        requestInput.sendKeys(request);
        searchButton.click();
    }

    public void authorize (String login, String password) {
        loginInput.sendKeys(login);
        passwordInput.sendKeys(login);
        authorizeButton.click();
    }
}
Steps
public class CommonUserSteps {

    public CommonUserSteps(WebDriver driver) {
        ...
    }

    public SearchPage onSearchPage() {
        return searchPage;
    }

    public void loginAsCommonUser() {
        User user = UserFactory.getCommonUser();
        onSearchPage().authorize(user.getLogin, user.getPassword);
    }

    public void searchFor(String request) {
        onSearchPage().searchFor(request);
    }

    public void shouldSeeSearchResults() {
        assertTrue(onSearchPage().isSearchResultsBlockDisplayed());
    }
}
Tests
public class SearchResultsTest {
    private WebDriver driver = new FirefoxDriver();
    private CommonUserSteps user = new CommonUserSteps(driver);

    @Before
    public void loadPage() {
        driver.get("http://www.yandex.ru");
    }

    @Test
    public void shouldSeeSearchResultsWhenLookingUp() {
        user.searchFor("CodeFest");
        user.shouldSeeSearchResults();
    }

    @After
    public void closeDriver() {
        driver.quit();
    }
}
Tests

 Steps

PageObjects
Tests

 Steps

PageObjects
Модель устройчива
Tests

 Steps

PageObjects
Шаблонизаторы
Шаблонизаторы
Шаблонизаторы
Шаблонизаторы
Шаблонизаторы
Шаблонизаторы
Шаблонизаторы
Шаблонизаторы
Загромождение
Загромождение
Загромождение
public class AutoHomePage {
    @FindBy(name = "text")
    private WebElement requestInput;

    @FindBy(xpath = "//input[@type='submit']")
    private WebElement searchButton;

    @FindBy(name = "login")
    private WebElement loginInput;

    @FindBy(name = "passwd")
    private WebElement passwordInput;

    @FindBy(xpath = "//div[@class='b-domik__button']//input")
    private WebElement loginButton;

    @FindBy(name = "twoweeks")
    private WebElement rememberMeCheckBox;

    @FindBy(name = "text")
Загромождение
    public class AutoHomePage {
        @FindBy(name = "text")
        private WebElement requestInput;

        @FindBy(xpath = "//input[@type='submit']")
        private WebElement searchButton;

        @FindBy(name = "login")
        private WebElement loginInput;

        @FindBy(name = "passwd")
        private WebElement passwordInput;

        @FindBy(xpath = "//div[@class='b-domik__button']//input")
        private WebElement loginButton;

        @FindBy(name = "twoweeks")
        private WebElement rememberMeCheckBox;

        @FindBy(name = "text")
        private WebElement requestInput;

        @FindBy(xpath = "//input[@type='submit']")
        private WebElement searchButton;

        @FindBy(name = "login")
        private WebElement loginInput;

        @FindBy(name = "passwd")
        private WebElement passwordInput;

        @FindBy(xpath = "//div[@class='b-domik__button']//input")
        private WebElement loginButton;

        @FindBy(name = "text")
        private WebElement requestInput;

        @FindBy(xpath = "//input[@type='submit']")
        private WebElement searchButton;

        @FindBy(name = "login")
        private WebElement loginInput;

        @FindBy(name = "passwd")
        private WebElement passwordInput;

        @FindBy(xpath = "//div[@class='b-domik__button']//input")
        private WebElement loginButton;
Загромождение
      public class AutoHomePage {
          @FindBy(name = "text")
          private WebElement requestInput;

          @FindBy(xpath = "//input[@type='submit']")
          private WebElement searchButton;

          @FindBy(name = "login")
          private WebElement loginInput;

          @FindBy(name = "passwd")
          private WebElement passwordInput;

          @FindBy(xpath = "//div[@class='b-domik__button']//input")
          private WebElement loginButton;

          @FindBy(name = "twoweeks")
          private WebElement rememberMeCheckBox;

          @FindBy(name = "text")
          private WebElement requestInput;

          @FindBy(xpath = "//input[@type='submit']")
          private WebElement searchButton;

          @FindBy(name = "login")
          private WebElement loginInput;

          @FindBy(name = "passwd")
          private WebElement passwordInput;

          @FindBy(xpath = "//div[@class='b-domik__button']//input")
          private WebElement loginButton;

          @FindBy(name = "text")
          private WebElement requestInput;

          @FindBy(xpath = "//input[@type='submit']")
          private WebElement searchButton;

          @FindBy(name = "login")
          private WebElement loginInput;

          @FindBy(name = "passwd")
          private WebElement passwordInput;

          @FindBy(xpath = "//div[@class='b-domik__button']//input")
          private WebElement loginButton;

          @FindBy(name = "text")
          private WebElement requestInput;

          @FindBy(xpath = "//input[@type='submit']")
          private WebElement searchButton;

          @FindBy(name = "login")
          private WebElement loginInput;

          @FindBy(name = "passwd")
          private WebElement passwordInput;

          @FindBy(xpath = "//div[@class='b-domik__button']//input")
          private WebElement loginButton;

          @FindBy(name = "text")
          private WebElement requestInput;

          @FindBy(xpath = "//input[@type='submit']")
          private WebElement searchButton;

          @FindBy(name = "login")
          private WebElement loginInput;

          @FindBy(name = "passwd")
          private WebElement passwordInput;

          @FindBy(xpath = "//div[@class='b-domik__button']//input")
          private WebElement loginButton;

          @FindBy(name = "text")
          private WebElement requestInput;

          @FindBy(xpath = "//input[@type='submit']")
          private WebElement searchButton;

          @FindBy(name = "login")
          private WebElement loginInput;

          @FindBy(name = "passwd")
          private WebElement passwordInput;

          @FindBy(xpath = "//div[@class='b-domik__button']//input")
          private WebElement loginButton;

          @FindBy(name = "text")
          private WebElement requestInput;

          @FindBy(xpath = "//input[@type='submit']")
          private WebElement searchButton;
Недостатки
Недостатки

   Дублирование кода
Недостатки

   Дублирование кода


    Загромождение
Коронное
 блюдо
Tests


  Steps

PageObject

 Element
PageObject


 Element
HtmlElements
Блоки элементов

Типизация элементов

Библиотека матчеров
Блоки элементов

Типизация элементов

Библиотека матчеров
PageObject


 Element
Поисковая форма

@Block(@FindBy(className = "b-head-search"))
public class SearchArrow extends HtmlElement {

    @FindBy(id = "text")
    private WebElement requestInput;

    @FindBy(className = "b-form-button__input")
    private WebElement searchButton;

    public void searchFor(String request) {
        requestInput.sendKeys(request);
        searchButton.click();
    }
}
Форма авторизации
@Block(@FindBy(className = "b-domik"))
public class AuthorizationForm extends HtmlElement {

    @FindBy(name = "login")
    private WebElement loginInput;

    @FindBy(name = "passwd")
    private WebElement passwordInput;

    @FindBy(className = "b-form-button__input")
    private WebElement authorizeButton;

    public void authorize(String login, String pass) {
        loginInput.sendKeys(login);
        passwordInput.sendKeys(password);
        authorizeButton.click();
    }
}
PageObject


 Element
Главная страница
public class SearchPage {
    @FindBy(id = "text")
    private WebElement requestInput;

    @FindBy(xpath = "//input[@type='submit']")
    private WebElement searchButton;

    @FindBy(name = "login")
    private WebElement loginInput;

    @FindBy(name = "passwd")
    private WebElement passwordInput;

    @FindBy(name = "b-form-button__input")
    private WebElement authorizeButton;

    public SearchPage(WebDriver driver) {
        PageFactory.initElements(driver, this);
    }

    ...
}
Главная страница
public class SearchPage {

    private SearchArrow searchArrow;

    private AuthorizationForm authorizationForm;

    public SearchPage(WebDriver driver) {
        HtmlElementLoader.populatePageObject(this, driver);
    }

    public void searchFor(String request) {
        searchArrow.searchFor(request);
    }

    public void login(String login, String password) {
        authorizationForm.login(login, password);
    }
}
Структура страницы
Переопределение
public class AutoSearchPage {

    @FindBy(className = "b-search")
    private SearchArrow searchArrow;

    private SearchResultsBlock searchResultsBlock;

    public SearchResultsPage(WebDriver driver) {
        HtmlElementLoader.populatePageObject(this, driver);
    }

    public void searchFor(String request) {
        searchArrow.searchFor(request);
    }

    public boolean isSearchResultsBlockDisplayed() {
        return searchResultsBlock.isDisplayed();
    }
}
Переопределение
public class SearchPage {

    @FindBy(className = "b-search")
    private SearchArrow searchArrow;

}


@Block(@FindBy(className = "b-head-search"))
public class SearchArrow extends HtmlElement {

    ...

}
Блоки элементов

Типизация элементов

Библиотека матчеров
Типизация
Типизация
   GodeFest
Типизация
   GodeFest
Поисковая форма
     GodeFest




@Block(@FindBy(className = "b-head-search"))
public class SearchArrow extends HtmlElement {
    @FindBy(id = "text")
    private WebElement requestInput;

    @FindBy(className = "b-form-button__input")
    private WebElement searchButton;

    @FindBy(xpath = "//div[@class='i-popup__content']//li")
    private List<WebElement> suggest;

    public void searchBySuggest(String request, int suggestItemNumber) {
        requestInput.sendKeys(request);
        suggest.get(suggestItemNumber).click();
    }
}
Поисковая форма
     GodeFest




@Block(@FindBy(className = "b-head-search"))
public class SearchArrow extends HtmlElement {
    @FindBy(id = "text")
    private WebElementrequestInput;
            TextInput requestInput;

    @FindBy(className = "b-form-button__input")
    private WebElement searchButton;
            Button searchButton;

    @FindBy(className = "i-popup__content")
    @FindBy(xpath = "//div[@class='i-popup__content']//li")
    private List<WebElement> suggest;
            Suggest suggest;

    public void searchBySuggest(String request, int suggestItemNumber) {
        requestInput.sendKeys(request);
        suggest.selectByIndex(suggestItemNumber);
        suggest.get(suggestItemNumber).click();
    }
}
Стандартные

TextBlock
TextInput
 Button
  Link
Расширенные



Checkbox
 Radio        Form
 Select       Table
Checkbox
public class Checkbox extends TypifiedElement {

    public WebElement getLabel(){...}

    public String getLabelText(){...}

    public String getText(){...}

    public void select(){...}

    public void deselect(){...}

    public void set(boolean checked){...}

    public boolean isSelected(){...}
}
Radio

public class Radio extends TypifiedElement {

    public List<WebElement> getButtons(){...}

    public WebElement getSelectedButton(){...}

    public void selectByValue(String value){...}

    public void selectByIndex(int index){...}

}
public class Select extends TypifiedElement {

    public boolean isMultiple(){...}
                                                   Select
    public List<WebElements> getOptions(){...}

    public List<WebElement> getAllSelectedOptions(){...}

    public WebElement getFirstSelectedOption(){...}

    public void selectByVisibleText(String text){...}

    public void selectByIndex(int index){...}

    public void selectByValue(String value){...}

    public void deselectAll(){...}

    public void deselectByValue(String value){...}

    public void deselectByIndex(int index){...}

    public void deselectByVisibleText(String text){...}
}
Form
public class Form extends TypifiedElement {

    public void fill(Map<String, Object> data){...}

    public <T> void fill(T bean, Converter Converter){...}

    protected WebElement findFiledByKey(String key){...}

    protected void fillField(WebElement e, Object value){...}

    public WebElement findFirstField(By by){...}

    public List<WebElement> findFields(By by){...}

    public List<WebElement> findSelectsBy(By by){...}

}
Form
public class SearchPage {

    @FindBy(className = "b-domik")
    private Form authorizationForm;

}




public class CommonUserSteps {

    public void loginAsCommonUser() {
        User user = UserFactory.getCommonUser();
        HashMap<String, Object> userHash = convert(user);
        onSearchPage().getAuthorizationForm.fill(userHash);
    }
}
Table
public class Table extends TypifiedElement {

    public List<WebElement> getHeadings(){...}

    public List<String> getHeadingsAsString(){...}

    public List<List<WebElement>> getRows(){...}

    public List<List<WebElement>> getColumns(){...}

    public WebElement getCellAt(int i, int j){...}

    public List<Map> getRowsMappedToHeadings() {...}

    public List<Map> getRowsMappedToHeadings(List<String> h){...}

    public List<Map> getRowsAsStringMappedToHeadings(){...}

    public List<Map> getRowsAsStringMappedToHeadings(List h){...}

}
Table
public class SomeSecretePage {

    @FindBy(className = "b-secret")
    private Table users;

}



public class SearchUserSteps {

    public List<User> findAllUsers() {
        Table usersTable = onSomeSecretPage().getUsersTable();
        List<Map> hash = usersTable.getRowsMappedToHeadings();
        List<User> users = convert(hash);
        return users;
    }
}
Converters
Поисковая форма
     GodeFest




@Block(@FindBy(className = "b-head-search"))
public class SearchArrow extends HtmlElement {
    @FindBy(id = "text")
    private TextInput requestInput;

    @FindBy(className = "b-form-button__input")
    private Button searchButton;

    @FindBy(className = "i-popup__content")
    private Suggest suggest;

    public void searchBySuggest(String request, int suggestItemNumber) {
        requestInput.sendKeys(request);
        suggest.selectByIndex(suggestItemNumber);
    }
}
Поисковая форма
     GodeFest




@Block(@FindBy(className = "b-head-search"))
public class SearchArrow extends HtmlElement {
    @FindBy(id = "text")
    private TextInput requestInput;

    @FindBy(className = "b-form-button__input")
    private Button searchButton;

    @FindBy(className = "i-popup__content")
    private Suggest suggest;

    public void searchBySuggest(String request, int suggestItemNumber) {
        requestInput.sendKeys(request);
        suggest.selectByIndex(suggestItemNumber);
    }
}
Добавление элементов
public class Suggest extends TypifiedElement {
    public Suggest(WebElement wrappedElement) {
        super(wrappedElement);
    }

    private List<WebElement> getItems() {
        return getWrappedElement().findElements(By.xpath("//li"));
    }

    public void selectByIndex(int itemIndex) {
        getItems().get(itemIndex).click();
    }

    public void selectByValue(String itemValue) {
        for (WebElement item : getItems()) {
            if (itemValue.equals(item.getText())) {
                item.click();
                return;
            }
        }
        throw new NoSuchElementException();
    }
}
Конструктор
                Страница




Типизированные элементы
Блоки элементов

Типизация элементов

Библиотека матчеров
Матчеры
Матчеры

assertThat(audience, isPayingAttention())
Матчеры

assertThat(audience, isPayingAttention())


assertThat(audience, is(not(sleeping())))
Матчеры элементов
Матчеры элементов
  assertThat(element, exists())
Матчеры элементов
      assertThat(element, exists())

assertThat(element, hasText(“CodeFest”))
Матчеры элементов
      assertThat(element, exists())

assertThat(element, hasText(“CodeFest”))

   assertThat(checkBox, isSelected())
Матчеры элементов
      assertThat(element, exists())

assertThat(element, hasText(“CodeFest”))

   assertThat(checkBox, isSelected())

assertThat(radio, hasSelectedButton(3))
Матчеры в степах

public class CommonUserSteps {

    public void shouldSeeSearchResults() {
       assertThat(
          onSearchPage().getSearchResults(), exist()
       );
    }
}
Матчеры в степах

public class CommonUserSteps {

    public void shouldSeeSearchResults() {
        assertThat(onSearchPage().getSearchResults(),
                both(exist()).and(isDisplayed()));
    }
}
Матчеры в степах

public class CommonUserSteps {

    public void shouldSeeSearchResults(Matcher mch) {
        assertThat(
           onSearchPage().getSearchResults(), mch
        );
    }
}
Матчеры в тестах

@Test
public void shouldSeeSearchResultsWhenLookingUp() {
    user.searchFor("CodeFest");
    user.shouldSeeSearchResults(
          both(exists()).and(isDisplayed())
    );
}
Вывод ошибки
@Test
public void shouldSeeSearchResultsWhenLookingUp() {
    user.searchFor("CodeFest");
    user.shouldSeeSearchResults(
          both(exists()).and(isDisplayed())
    );
}


  Expected: element existing on page
       but: was <[[FirefoxDriver: firefox on
  MAC (e3b28f2e-7aa7-
  a241-8807-40df2a8e0b54)] -> ...]>
Именование элементов

@Block(@FindBy(className = "b-head-search"))
public class SearchResultBlock extends HtmlElement {

    @Name("Список поисковых результатов")
    @FindBy(id = "results")
    private List<SearchResult> searchResults;

    @FindBy(id = "info")
    private TextBlock searchInfo;

}
Переопределение
public class SearchPage {

    @Name(“Блок поисковых результатов”)
    private SearchResultsBlock searchResultsBlock;

}


@Block(@FindBy(className = "b-head-search"))
public class SearchResultsBlock extends HtmlElement {

    ...

}
Вывод ошибки
@Test
public void shouldSeeSearchResultsWhenLookingUp() {
    user.searchFor("CodeFest");
    user.shouldSeeSearchResults(
          both(exists()).and(isDisplayed())
    );
}



   Expected: element existing on page
        but: was SearchResultBlock
Декораторы
Waiter Decorator

@Test
public void shouldSeeSearchResultsWhenLookingUp() {
    user.searchFor("CodeFest");
    user.shouldSeeSearchResults(
          should(exists()).whileWaitingUntil(timeoutHasExpired())
    );
}




   Expected: while waiting for [30000] ms
             element existing on page
        but: was SearchResultBlock
Action Decorator

@Test
public void shouldSeeSearchResultsWhenLookingUp() {
    user.searchFor("CodeFest");
    user.shouldSeeSearchResults(
          should(exists()).after(pageRefresh(driver))
    );
}




   Expected: after page refresh
             element existing on page
        but: was SearchResultBlock
Condition Decorator

@Test
public void shouldSeeSearchResultsWhenLookingUp() {
    user.searchFor("CodeFest");
    user.shouldSeeSearchResults(
          should(isDisplayed()).inCase(exists());
    );
}




   Expected: element displayed on page
             if element exists on page
        but: was SearchResultBlock
Блоки элементов

Типизация элементов

Библиотека матчеров
Будущее


   71
Библиотека элементов
Библиотека элементов
Генерация блоков
Генерация блоков




 Страница
Генерация блоков

            @Block(@FindBy(className = "b-head-search"))
              @Block(@FindBy(className = "b-head-search"))
            public class SearchArrow extends HtmlElement {
                @Block(@FindBy(className = "b-head-search"))
              public class SearchArrow extends HtmlElement {
                 @FindBy(id = "text")
                  @Block(@FindBy(className = "b-head-search"))
                public class SearchArrow extends HtmlElement {
                 private class=SearchArrow extends HtmlElement {
                   @FindBy(id     "text")
                  public WebElement requestInput;
                    @Block(@FindBy(className = "b-head-search"))
                     @FindBy(id = "text")
                   private class SearchArrow extends HtmlElement {
                    public WebElement requestInput;
                       @FindBy(id = "text")
                     private WebElement requestInput;
                 @FindBy(className == "text")
                         @FindBy(id     "b-form-button__input")
                       private WebElement requestInput;
                   @FindBy(className = "b-form-button__input")
                 private WebElement searchButton;
                         private WebElement requestInput;
                     @FindBy(className = "b-form-button__input")
                   private WebElement searchButton;
                       @FindBy(className = "b-form-button__input")
                     private WebElement searchButton;
                 public @FindBy(className searchButton; {
                       private searchFor(String request)
                          void WebElement = "b-form-button__input")
                   public void searchFor(String request) {
                      requestInput.sendKeys(request);
                         private WebElement searchButton;
                     public void searchFor(String request) {
                        requestInput.sendKeys(request);
                      searchButton.click();
                       public void searchFor(String request) {
                          requestInput.sendKeys(request);
                        searchButton.click();
                 }       public void searchFor(String request) {
                            requestInput.sendKeys(request);
                   }      searchButton.click();
            }                 requestInput.sendKeys(request);
                            searchButton.click();
              }      }
                       }      searchButton.click();
                }
                  }      }
                    }




 Страница                     Блоки
Попробуйте
   сами
Tests


  Steps

PageObject

 Element
HtmlElements
Технологии


    Converter = LambdaJ
    Step FRWK = 2CDDs
    Matchers = Hamcrest
@eroshenkoam

https://github.com/yandex-qatools/htmlelements


https://groups.google.com/forum/?fromgroups#!
      forum/yandex-qatools-htmlelements


        qa-tools@yandex-team.ru

More Related Content

What's hot

Unobtrusive javascript with jQuery
Unobtrusive javascript with jQueryUnobtrusive javascript with jQuery
Unobtrusive javascript with jQuery
Angel Ruiz
 
SharePoint Cincy 2012 - jQuery essentials
SharePoint Cincy 2012 - jQuery essentialsSharePoint Cincy 2012 - jQuery essentials
SharePoint Cincy 2012 - jQuery essentials
Mark Rackley
 

What's hot (20)

SharePoint and jQuery Essentials
SharePoint and jQuery EssentialsSharePoint and jQuery Essentials
SharePoint and jQuery Essentials
 
J query training
J query trainingJ query training
J query training
 
Simple Web Development in Java
Simple Web Development in JavaSimple Web Development in Java
Simple Web Development in Java
 
Intorduction of Playframework
Intorduction of PlayframeworkIntorduction of Playframework
Intorduction of Playframework
 
Introduction to jQuery
Introduction to jQueryIntroduction to jQuery
Introduction to jQuery
 
Write Less Do More
Write Less Do MoreWrite Less Do More
Write Less Do More
 
Unobtrusive javascript with jQuery
Unobtrusive javascript with jQueryUnobtrusive javascript with jQuery
Unobtrusive javascript with jQuery
 
jQuery for beginners
jQuery for beginnersjQuery for beginners
jQuery for beginners
 
Organizing Code with JavascriptMVC
Organizing Code with JavascriptMVCOrganizing Code with JavascriptMVC
Organizing Code with JavascriptMVC
 
jQuery
jQueryjQuery
jQuery
 
SharePoint Cincy 2012 - jQuery essentials
SharePoint Cincy 2012 - jQuery essentialsSharePoint Cincy 2012 - jQuery essentials
SharePoint Cincy 2012 - jQuery essentials
 
A Rich Web experience with jQuery, Ajax and .NET
A Rich Web experience with jQuery, Ajax and .NETA Rich Web experience with jQuery, Ajax and .NET
A Rich Web experience with jQuery, Ajax and .NET
 
jQuery Features to Avoid
jQuery Features to AvoidjQuery Features to Avoid
jQuery Features to Avoid
 
jQuery from the very beginning
jQuery from the very beginningjQuery from the very beginning
jQuery from the very beginning
 
A Rich Web Experience with jQuery, Ajax and .NET
A Rich Web Experience with jQuery, Ajax and .NETA Rich Web Experience with jQuery, Ajax and .NET
A Rich Web Experience with jQuery, Ajax and .NET
 
Jquery
JqueryJquery
Jquery
 
Round pegs and square holes
Round pegs and square holesRound pegs and square holes
Round pegs and square holes
 
jQuery
jQueryjQuery
jQuery
 
jQuery Fundamentals
jQuery FundamentalsjQuery Fundamentals
jQuery Fundamentals
 
jQuery Loves Developers - Oredev 2009
jQuery Loves Developers - Oredev 2009jQuery Loves Developers - Oredev 2009
jQuery Loves Developers - Oredev 2009
 

Similar to CodeFest 2013. Ерошенко А. — Фреймворк Html Elements или как удобно взаимодействовать с веб-интерфейсами в тестах

Create an advance data type to represent web page history. Name this .pdf
Create an advance data type to represent web page history. Name this .pdfCreate an advance data type to represent web page history. Name this .pdf
Create an advance data type to represent web page history. Name this .pdf
sanuoptical
 
HTML5 - The 2012 of the Web - Adobe MAX
HTML5 - The 2012 of the Web - Adobe MAXHTML5 - The 2012 of the Web - Adobe MAX
HTML5 - The 2012 of the Web - Adobe MAX
Robert Nyman
 

Similar to CodeFest 2013. Ерошенко А. — Фреймворк Html Elements или как удобно взаимодействовать с веб-интерфейсами в тестах (20)

HtmlElements – естественное расширение PageObject
HtmlElements – естественное расширение PageObjectHtmlElements – естественное расширение PageObject
HtmlElements – естественное расширение PageObject
 
Session on "The Screenplay Pattern: Better Interactions for Better Automation...
Session on "The Screenplay Pattern: Better Interactions for Better Automation...Session on "The Screenplay Pattern: Better Interactions for Better Automation...
Session on "The Screenplay Pattern: Better Interactions for Better Automation...
 
QA Fest 2017. Ярослав Святкин. Тестовый фреймворк GEB для тестирования WEB пр...
QA Fest 2017. Ярослав Святкин. Тестовый фреймворк GEB для тестирования WEB пр...QA Fest 2017. Ярослав Святкин. Тестовый фреймворк GEB для тестирования WEB пр...
QA Fest 2017. Ярослав Святкин. Тестовый фреймворк GEB для тестирования WEB пр...
 
A test framework out of the box - Geb for Web and mobile
A test framework out of the box - Geb for Web and mobileA test framework out of the box - Geb for Web and mobile
A test framework out of the box - Geb for Web and mobile
 
Creating a Facebook Clone - Part XXXI - Transcript.pdf
Creating a Facebook Clone - Part XXXI - Transcript.pdfCreating a Facebook Clone - Part XXXI - Transcript.pdf
Creating a Facebook Clone - Part XXXI - Transcript.pdf
 
Обзор автоматизации тестирования на JavaScript
Обзор автоматизации тестирования на JavaScriptОбзор автоматизации тестирования на JavaScript
Обзор автоматизации тестирования на JavaScript
 
Create an advance data type to represent web page history. Name this .pdf
Create an advance data type to represent web page history. Name this .pdfCreate an advance data type to represent web page history. Name this .pdf
Create an advance data type to represent web page history. Name this .pdf
 
InheritedWidget is your friend - GDG London (2018-08-08)
InheritedWidget is your friend - GDG London (2018-08-08)InheritedWidget is your friend - GDG London (2018-08-08)
InheritedWidget is your friend - GDG London (2018-08-08)
 
Beyond pageobjects
Beyond pageobjectsBeyond pageobjects
Beyond pageobjects
 
[QE 2017] Tomasz Kras - SOLIDne Page Objecty — Screenplay Pattern w akcji
[QE 2017] Tomasz Kras - SOLIDne Page Objecty — Screenplay Pattern w akcji[QE 2017] Tomasz Kras - SOLIDne Page Objecty — Screenplay Pattern w akcji
[QE 2017] Tomasz Kras - SOLIDne Page Objecty — Screenplay Pattern w akcji
 
Jquery introduction
Jquery introductionJquery introduction
Jquery introduction
 
Тройничок: Selenide для Web, Android и iOS
Тройничок: Selenide для Web, Android и iOSТройничок: Selenide для Web, Android и iOS
Тройничок: Selenide для Web, Android и iOS
 
Android ui layouts ,cntls,webservices examples codes
Android ui layouts ,cntls,webservices examples codesAndroid ui layouts ,cntls,webservices examples codes
Android ui layouts ,cntls,webservices examples codes
 
Windows ストアーアプリで SQLite を使ってみよう
Windows ストアーアプリで SQLite を使ってみようWindows ストアーアプリで SQLite を使ってみよう
Windows ストアーアプリで SQLite を使ってみよう
 
Architecure components by Paulina Szklarska
Architecure components by Paulina SzklarskaArchitecure components by Paulina Szklarska
Architecure components by Paulina Szklarska
 
Роман Иовлев «Open Source UI Automation Tests on C#»
Роман Иовлев «Open Source UI Automation Tests on C#»Роман Иовлев «Open Source UI Automation Tests on C#»
Роман Иовлев «Open Source UI Automation Tests on C#»
 
Diving into php
Diving into phpDiving into php
Diving into php
 
HTML5 - The 2012 of the Web - Adobe MAX
HTML5 - The 2012 of the Web - Adobe MAXHTML5 - The 2012 of the Web - Adobe MAX
HTML5 - The 2012 of the Web - Adobe MAX
 
Creating a Facebook Clone - Part XXXI.pdf
Creating a Facebook Clone - Part XXXI.pdfCreating a Facebook Clone - Part XXXI.pdf
Creating a Facebook Clone - Part XXXI.pdf
 
Introduction to Spring Boot.pdf
Introduction to Spring Boot.pdfIntroduction to Spring Boot.pdf
Introduction to Spring Boot.pdf
 

More from CodeFest

More from CodeFest (20)

Alexander Graebe
Alexander GraebeAlexander Graebe
Alexander Graebe
 
Никита Прокопов
Никита ПрокоповНикита Прокопов
Никита Прокопов
 
Денис Баталов
Денис БаталовДенис Баталов
Денис Баталов
 
Елена Гальцина
Елена ГальцинаЕлена Гальцина
Елена Гальцина
 
Александр Калашников
Александр КалашниковАлександр Калашников
Александр Калашников
 
Ирина Иванова
Ирина ИвановаИрина Иванова
Ирина Иванова
 
Marko Berković
Marko BerkovićMarko Berković
Marko Berković
 
Денис Кортунов
Денис КортуновДенис Кортунов
Денис Кортунов
 
Александр Зимин
Александр ЗиминАлександр Зимин
Александр Зимин
 
Сергей Крапивенский
Сергей КрапивенскийСергей Крапивенский
Сергей Крапивенский
 
Сергей Игнатов
Сергей ИгнатовСергей Игнатов
Сергей Игнатов
 
Николай Крапивный
Николай КрапивныйНиколай Крапивный
Николай Крапивный
 
Alexander Graebe
Alexander GraebeAlexander Graebe
Alexander Graebe
 
Вадим Смирнов
Вадим СмирновВадим Смирнов
Вадим Смирнов
 
Константин Осипов
Константин ОсиповКонстантин Осипов
Константин Осипов
 
Raffaele Rialdi
Raffaele RialdiRaffaele Rialdi
Raffaele Rialdi
 
Максим Пугачев
Максим ПугачевМаксим Пугачев
Максим Пугачев
 
Rene Groeschke
Rene GroeschkeRene Groeschke
Rene Groeschke
 
Иван Бондаренко
Иван БондаренкоИван Бондаренко
Иван Бондаренко
 
Mete Atamel
Mete AtamelMete Atamel
Mete Atamel
 

Recently uploaded

Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
Joaquim Jorge
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Service
giselly40
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
vu2urc
 

Recently uploaded (20)

Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUnderstanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Service
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024
 
Tech Trends Report 2024 Future Today Institute.pdf
Tech Trends Report 2024 Future Today Institute.pdfTech Trends Report 2024 Future Today Institute.pdf
Tech Trends Report 2024 Future Today Institute.pdf
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 

CodeFest 2013. Ерошенко А. — Фреймворк Html Elements или как удобно взаимодействовать с веб-интерфейсами в тестах

  • 2.
  • 8.
  • 10. public class SearchPage { @FindBy(id = "text") private WebElement requestInput; @FindBy(xpath = "//input[@type='submit']") private WebElement searchButton; @FindBy(name = "login") private WebElement loginInput; @FindBy(name = "passwd") private WebElement passwordInput; @FindBy(name = "b-form-button__input") private WebElement authorizeButton; public SearchPage(WebDriver driver) { PageFactory.initElements(driver, this); } public void searchFor(String request) { requestInput.sendKeys(request); searchButton.click(); } public void authorize (String login, String password) { loginInput.sendKeys(login); passwordInput.sendKeys(login); authorizeButton.click(); } }
  • 11. Steps
  • 12. public class CommonUserSteps { public CommonUserSteps(WebDriver driver) { ... } public SearchPage onSearchPage() { return searchPage; } public void loginAsCommonUser() { User user = UserFactory.getCommonUser(); onSearchPage().authorize(user.getLogin, user.getPassword); } public void searchFor(String request) { onSearchPage().searchFor(request); } public void shouldSeeSearchResults() { assertTrue(onSearchPage().isSearchResultsBlockDisplayed()); } }
  • 13. Tests
  • 14. public class SearchResultsTest { private WebDriver driver = new FirefoxDriver(); private CommonUserSteps user = new CommonUserSteps(driver); @Before public void loadPage() { driver.get("http://www.yandex.ru"); } @Test public void shouldSeeSearchResultsWhenLookingUp() { user.searchFor("CodeFest"); user.shouldSeeSearchResults(); } @After public void closeDriver() { driver.quit(); } }
  • 29. Загромождение public class AutoHomePage { @FindBy(name = "text") private WebElement requestInput; @FindBy(xpath = "//input[@type='submit']") private WebElement searchButton; @FindBy(name = "login") private WebElement loginInput; @FindBy(name = "passwd") private WebElement passwordInput; @FindBy(xpath = "//div[@class='b-domik__button']//input") private WebElement loginButton; @FindBy(name = "twoweeks") private WebElement rememberMeCheckBox; @FindBy(name = "text")
  • 30. Загромождение public class AutoHomePage { @FindBy(name = "text") private WebElement requestInput; @FindBy(xpath = "//input[@type='submit']") private WebElement searchButton; @FindBy(name = "login") private WebElement loginInput; @FindBy(name = "passwd") private WebElement passwordInput; @FindBy(xpath = "//div[@class='b-domik__button']//input") private WebElement loginButton; @FindBy(name = "twoweeks") private WebElement rememberMeCheckBox; @FindBy(name = "text") private WebElement requestInput; @FindBy(xpath = "//input[@type='submit']") private WebElement searchButton; @FindBy(name = "login") private WebElement loginInput; @FindBy(name = "passwd") private WebElement passwordInput; @FindBy(xpath = "//div[@class='b-domik__button']//input") private WebElement loginButton; @FindBy(name = "text") private WebElement requestInput; @FindBy(xpath = "//input[@type='submit']") private WebElement searchButton; @FindBy(name = "login") private WebElement loginInput; @FindBy(name = "passwd") private WebElement passwordInput; @FindBy(xpath = "//div[@class='b-domik__button']//input") private WebElement loginButton;
  • 31. Загромождение public class AutoHomePage { @FindBy(name = "text") private WebElement requestInput; @FindBy(xpath = "//input[@type='submit']") private WebElement searchButton; @FindBy(name = "login") private WebElement loginInput; @FindBy(name = "passwd") private WebElement passwordInput; @FindBy(xpath = "//div[@class='b-domik__button']//input") private WebElement loginButton; @FindBy(name = "twoweeks") private WebElement rememberMeCheckBox; @FindBy(name = "text") private WebElement requestInput; @FindBy(xpath = "//input[@type='submit']") private WebElement searchButton; @FindBy(name = "login") private WebElement loginInput; @FindBy(name = "passwd") private WebElement passwordInput; @FindBy(xpath = "//div[@class='b-domik__button']//input") private WebElement loginButton; @FindBy(name = "text") private WebElement requestInput; @FindBy(xpath = "//input[@type='submit']") private WebElement searchButton; @FindBy(name = "login") private WebElement loginInput; @FindBy(name = "passwd") private WebElement passwordInput; @FindBy(xpath = "//div[@class='b-domik__button']//input") private WebElement loginButton; @FindBy(name = "text") private WebElement requestInput; @FindBy(xpath = "//input[@type='submit']") private WebElement searchButton; @FindBy(name = "login") private WebElement loginInput; @FindBy(name = "passwd") private WebElement passwordInput; @FindBy(xpath = "//div[@class='b-domik__button']//input") private WebElement loginButton; @FindBy(name = "text") private WebElement requestInput; @FindBy(xpath = "//input[@type='submit']") private WebElement searchButton; @FindBy(name = "login") private WebElement loginInput; @FindBy(name = "passwd") private WebElement passwordInput; @FindBy(xpath = "//div[@class='b-domik__button']//input") private WebElement loginButton; @FindBy(name = "text") private WebElement requestInput; @FindBy(xpath = "//input[@type='submit']") private WebElement searchButton; @FindBy(name = "login") private WebElement loginInput; @FindBy(name = "passwd") private WebElement passwordInput; @FindBy(xpath = "//div[@class='b-domik__button']//input") private WebElement loginButton; @FindBy(name = "text") private WebElement requestInput; @FindBy(xpath = "//input[@type='submit']") private WebElement searchButton;
  • 33. Недостатки Дублирование кода
  • 34. Недостатки Дублирование кода Загромождение
  • 41.
  • 42.
  • 44. Поисковая форма @Block(@FindBy(className = "b-head-search")) public class SearchArrow extends HtmlElement { @FindBy(id = "text") private WebElement requestInput; @FindBy(className = "b-form-button__input") private WebElement searchButton; public void searchFor(String request) { requestInput.sendKeys(request); searchButton.click(); } }
  • 45. Форма авторизации @Block(@FindBy(className = "b-domik")) public class AuthorizationForm extends HtmlElement { @FindBy(name = "login") private WebElement loginInput; @FindBy(name = "passwd") private WebElement passwordInput; @FindBy(className = "b-form-button__input") private WebElement authorizeButton; public void authorize(String login, String pass) { loginInput.sendKeys(login); passwordInput.sendKeys(password); authorizeButton.click(); } }
  • 47. Главная страница public class SearchPage { @FindBy(id = "text") private WebElement requestInput; @FindBy(xpath = "//input[@type='submit']") private WebElement searchButton; @FindBy(name = "login") private WebElement loginInput; @FindBy(name = "passwd") private WebElement passwordInput; @FindBy(name = "b-form-button__input") private WebElement authorizeButton; public SearchPage(WebDriver driver) { PageFactory.initElements(driver, this); } ... }
  • 48. Главная страница public class SearchPage { private SearchArrow searchArrow; private AuthorizationForm authorizationForm; public SearchPage(WebDriver driver) { HtmlElementLoader.populatePageObject(this, driver); } public void searchFor(String request) { searchArrow.searchFor(request); } public void login(String login, String password) { authorizationForm.login(login, password); } }
  • 50. Переопределение public class AutoSearchPage { @FindBy(className = "b-search") private SearchArrow searchArrow; private SearchResultsBlock searchResultsBlock; public SearchResultsPage(WebDriver driver) { HtmlElementLoader.populatePageObject(this, driver); } public void searchFor(String request) { searchArrow.searchFor(request); } public boolean isSearchResultsBlockDisplayed() { return searchResultsBlock.isDisplayed(); } }
  • 51. Переопределение public class SearchPage { @FindBy(className = "b-search") private SearchArrow searchArrow; } @Block(@FindBy(className = "b-head-search")) public class SearchArrow extends HtmlElement { ... }
  • 54. Типизация GodeFest
  • 55. Типизация GodeFest
  • 56. Поисковая форма GodeFest @Block(@FindBy(className = "b-head-search")) public class SearchArrow extends HtmlElement { @FindBy(id = "text") private WebElement requestInput; @FindBy(className = "b-form-button__input") private WebElement searchButton; @FindBy(xpath = "//div[@class='i-popup__content']//li") private List<WebElement> suggest; public void searchBySuggest(String request, int suggestItemNumber) { requestInput.sendKeys(request); suggest.get(suggestItemNumber).click(); } }
  • 57. Поисковая форма GodeFest @Block(@FindBy(className = "b-head-search")) public class SearchArrow extends HtmlElement { @FindBy(id = "text") private WebElementrequestInput; TextInput requestInput; @FindBy(className = "b-form-button__input") private WebElement searchButton; Button searchButton; @FindBy(className = "i-popup__content") @FindBy(xpath = "//div[@class='i-popup__content']//li") private List<WebElement> suggest; Suggest suggest; public void searchBySuggest(String request, int suggestItemNumber) { requestInput.sendKeys(request); suggest.selectByIndex(suggestItemNumber); suggest.get(suggestItemNumber).click(); } }
  • 60. Checkbox public class Checkbox extends TypifiedElement { public WebElement getLabel(){...} public String getLabelText(){...} public String getText(){...} public void select(){...} public void deselect(){...} public void set(boolean checked){...} public boolean isSelected(){...} }
  • 61. Radio public class Radio extends TypifiedElement { public List<WebElement> getButtons(){...} public WebElement getSelectedButton(){...} public void selectByValue(String value){...} public void selectByIndex(int index){...} }
  • 62. public class Select extends TypifiedElement { public boolean isMultiple(){...} Select public List<WebElements> getOptions(){...} public List<WebElement> getAllSelectedOptions(){...} public WebElement getFirstSelectedOption(){...} public void selectByVisibleText(String text){...} public void selectByIndex(int index){...} public void selectByValue(String value){...} public void deselectAll(){...} public void deselectByValue(String value){...} public void deselectByIndex(int index){...} public void deselectByVisibleText(String text){...} }
  • 63. Form public class Form extends TypifiedElement { public void fill(Map<String, Object> data){...} public <T> void fill(T bean, Converter Converter){...} protected WebElement findFiledByKey(String key){...} protected void fillField(WebElement e, Object value){...} public WebElement findFirstField(By by){...} public List<WebElement> findFields(By by){...} public List<WebElement> findSelectsBy(By by){...} }
  • 64. Form public class SearchPage { @FindBy(className = "b-domik") private Form authorizationForm; } public class CommonUserSteps { public void loginAsCommonUser() { User user = UserFactory.getCommonUser(); HashMap<String, Object> userHash = convert(user); onSearchPage().getAuthorizationForm.fill(userHash); } }
  • 65. Table public class Table extends TypifiedElement { public List<WebElement> getHeadings(){...} public List<String> getHeadingsAsString(){...} public List<List<WebElement>> getRows(){...} public List<List<WebElement>> getColumns(){...} public WebElement getCellAt(int i, int j){...} public List<Map> getRowsMappedToHeadings() {...} public List<Map> getRowsMappedToHeadings(List<String> h){...} public List<Map> getRowsAsStringMappedToHeadings(){...} public List<Map> getRowsAsStringMappedToHeadings(List h){...} }
  • 66. Table public class SomeSecretePage { @FindBy(className = "b-secret") private Table users; } public class SearchUserSteps { public List<User> findAllUsers() { Table usersTable = onSomeSecretPage().getUsersTable(); List<Map> hash = usersTable.getRowsMappedToHeadings(); List<User> users = convert(hash); return users; } }
  • 68. Поисковая форма GodeFest @Block(@FindBy(className = "b-head-search")) public class SearchArrow extends HtmlElement { @FindBy(id = "text") private TextInput requestInput; @FindBy(className = "b-form-button__input") private Button searchButton; @FindBy(className = "i-popup__content") private Suggest suggest; public void searchBySuggest(String request, int suggestItemNumber) { requestInput.sendKeys(request); suggest.selectByIndex(suggestItemNumber); } }
  • 69. Поисковая форма GodeFest @Block(@FindBy(className = "b-head-search")) public class SearchArrow extends HtmlElement { @FindBy(id = "text") private TextInput requestInput; @FindBy(className = "b-form-button__input") private Button searchButton; @FindBy(className = "i-popup__content") private Suggest suggest; public void searchBySuggest(String request, int suggestItemNumber) { requestInput.sendKeys(request); suggest.selectByIndex(suggestItemNumber); } }
  • 70. Добавление элементов public class Suggest extends TypifiedElement { public Suggest(WebElement wrappedElement) { super(wrappedElement); } private List<WebElement> getItems() { return getWrappedElement().findElements(By.xpath("//li")); } public void selectByIndex(int itemIndex) { getItems().get(itemIndex).click(); } public void selectByValue(String itemValue) { for (WebElement item : getItems()) { if (itemValue.equals(item.getText())) { item.click(); return; } } throw new NoSuchElementException(); } }
  • 71. Конструктор Страница Типизированные элементы
  • 77. Матчеры элементов assertThat(element, exists())
  • 78. Матчеры элементов assertThat(element, exists()) assertThat(element, hasText(“CodeFest”))
  • 79. Матчеры элементов assertThat(element, exists()) assertThat(element, hasText(“CodeFest”)) assertThat(checkBox, isSelected())
  • 80. Матчеры элементов assertThat(element, exists()) assertThat(element, hasText(“CodeFest”)) assertThat(checkBox, isSelected()) assertThat(radio, hasSelectedButton(3))
  • 81. Матчеры в степах public class CommonUserSteps { public void shouldSeeSearchResults() { assertThat( onSearchPage().getSearchResults(), exist() ); } }
  • 82. Матчеры в степах public class CommonUserSteps { public void shouldSeeSearchResults() { assertThat(onSearchPage().getSearchResults(), both(exist()).and(isDisplayed())); } }
  • 83. Матчеры в степах public class CommonUserSteps { public void shouldSeeSearchResults(Matcher mch) { assertThat( onSearchPage().getSearchResults(), mch ); } }
  • 84. Матчеры в тестах @Test public void shouldSeeSearchResultsWhenLookingUp() { user.searchFor("CodeFest"); user.shouldSeeSearchResults( both(exists()).and(isDisplayed()) ); }
  • 85. Вывод ошибки @Test public void shouldSeeSearchResultsWhenLookingUp() { user.searchFor("CodeFest"); user.shouldSeeSearchResults( both(exists()).and(isDisplayed()) ); } Expected: element existing on page but: was <[[FirefoxDriver: firefox on MAC (e3b28f2e-7aa7- a241-8807-40df2a8e0b54)] -> ...]>
  • 86. Именование элементов @Block(@FindBy(className = "b-head-search")) public class SearchResultBlock extends HtmlElement { @Name("Список поисковых результатов") @FindBy(id = "results") private List<SearchResult> searchResults; @FindBy(id = "info") private TextBlock searchInfo; }
  • 87. Переопределение public class SearchPage { @Name(“Блок поисковых результатов”) private SearchResultsBlock searchResultsBlock; } @Block(@FindBy(className = "b-head-search")) public class SearchResultsBlock extends HtmlElement { ... }
  • 88. Вывод ошибки @Test public void shouldSeeSearchResultsWhenLookingUp() { user.searchFor("CodeFest"); user.shouldSeeSearchResults( both(exists()).and(isDisplayed()) ); } Expected: element existing on page but: was SearchResultBlock
  • 90. Waiter Decorator @Test public void shouldSeeSearchResultsWhenLookingUp() { user.searchFor("CodeFest"); user.shouldSeeSearchResults( should(exists()).whileWaitingUntil(timeoutHasExpired()) ); } Expected: while waiting for [30000] ms element existing on page but: was SearchResultBlock
  • 91. Action Decorator @Test public void shouldSeeSearchResultsWhenLookingUp() { user.searchFor("CodeFest"); user.shouldSeeSearchResults( should(exists()).after(pageRefresh(driver)) ); } Expected: after page refresh element existing on page but: was SearchResultBlock
  • 92. Condition Decorator @Test public void shouldSeeSearchResultsWhenLookingUp() { user.searchFor("CodeFest"); user.shouldSeeSearchResults( should(isDisplayed()).inCase(exists()); ); } Expected: element displayed on page if element exists on page but: was SearchResultBlock
  • 99. Генерация блоков @Block(@FindBy(className = "b-head-search")) @Block(@FindBy(className = "b-head-search")) public class SearchArrow extends HtmlElement { @Block(@FindBy(className = "b-head-search")) public class SearchArrow extends HtmlElement { @FindBy(id = "text") @Block(@FindBy(className = "b-head-search")) public class SearchArrow extends HtmlElement { private class=SearchArrow extends HtmlElement { @FindBy(id "text") public WebElement requestInput; @Block(@FindBy(className = "b-head-search")) @FindBy(id = "text") private class SearchArrow extends HtmlElement { public WebElement requestInput; @FindBy(id = "text") private WebElement requestInput; @FindBy(className == "text") @FindBy(id "b-form-button__input") private WebElement requestInput; @FindBy(className = "b-form-button__input") private WebElement searchButton; private WebElement requestInput; @FindBy(className = "b-form-button__input") private WebElement searchButton; @FindBy(className = "b-form-button__input") private WebElement searchButton; public @FindBy(className searchButton; { private searchFor(String request) void WebElement = "b-form-button__input") public void searchFor(String request) { requestInput.sendKeys(request); private WebElement searchButton; public void searchFor(String request) { requestInput.sendKeys(request); searchButton.click(); public void searchFor(String request) { requestInput.sendKeys(request); searchButton.click(); } public void searchFor(String request) { requestInput.sendKeys(request); } searchButton.click(); } requestInput.sendKeys(request); searchButton.click(); } } } searchButton.click(); } } } } Страница Блоки
  • 100. Попробуйте сами
  • 103. Технологии Converter = LambdaJ Step FRWK = 2CDDs Matchers = Hamcrest