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

SharePoint and jQuery Essentials
SharePoint and jQuery EssentialsSharePoint and jQuery Essentials
SharePoint and jQuery EssentialsMark Rackley
 
Simple Web Development in Java
Simple Web Development in JavaSimple Web Development in Java
Simple Web Development in JavaVincent Tencé
 
Intorduction of Playframework
Intorduction of PlayframeworkIntorduction of Playframework
Intorduction of Playframeworkmaltiyadav
 
Introduction to jQuery
Introduction to jQueryIntroduction to jQuery
Introduction to jQueryZeeshan Khan
 
Write Less Do More
Write Less Do MoreWrite Less Do More
Write Less Do MoreRemy Sharp
 
Unobtrusive javascript with jQuery
Unobtrusive javascript with jQueryUnobtrusive javascript with jQuery
Unobtrusive javascript with jQueryAngel Ruiz
 
Organizing Code with JavascriptMVC
Organizing Code with JavascriptMVCOrganizing Code with JavascriptMVC
Organizing Code with JavascriptMVCThomas Reynolds
 
SharePoint Cincy 2012 - jQuery essentials
SharePoint Cincy 2012 - jQuery essentialsSharePoint Cincy 2012 - jQuery essentials
SharePoint Cincy 2012 - jQuery essentialsMark Rackley
 
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 .NETJames Johnson
 
jQuery Features to Avoid
jQuery Features to AvoidjQuery Features to Avoid
jQuery Features to Avoiddmethvin
 
jQuery from the very beginning
jQuery from the very beginningjQuery from the very beginning
jQuery from the very beginningAnis Ahmad
 
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 .NETJames Johnson
 
Round pegs and square holes
Round pegs and square holesRound pegs and square holes
Round pegs and square holesDaniel Greenfeld
 
jQuery Fundamentals
jQuery FundamentalsjQuery Fundamentals
jQuery FundamentalsGil Fink
 
jQuery Loves Developers - Oredev 2009
jQuery Loves Developers - Oredev 2009jQuery Loves Developers - Oredev 2009
jQuery Loves Developers - Oredev 2009Remy Sharp
 

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 или как удобно взаимодействовать с веб-интерфейсами в тестах

HtmlElements – естественное расширение PageObject
HtmlElements – естественное расширение PageObjectHtmlElements – естественное расширение PageObject
HtmlElements – естественное расширение PageObjectSQALab
 
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...Agile Testing Alliance
 
QA Fest 2017. Ярослав Святкин. Тестовый фреймворк GEB для тестирования WEB пр...
QA Fest 2017. Ярослав Святкин. Тестовый фреймворк GEB для тестирования WEB пр...QA Fest 2017. Ярослав Святкин. Тестовый фреймворк GEB для тестирования WEB пр...
QA Fest 2017. Ярослав Святкин. Тестовый фреймворк GEB для тестирования WEB пр...QAFest
 
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 mobileGlobalLogic Ukraine
 
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.pdfShaiAlmog1
 
Обзор автоматизации тестирования на JavaScript
Обзор автоматизации тестирования на JavaScriptОбзор автоматизации тестирования на JavaScript
Обзор автоматизации тестирования на JavaScriptCOMAQA.BY
 
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 .pdfsanuoptical
 
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)Andrea Bizzotto
 
[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 akcjiFuture Processing
 
Тройничок: Selenide для Web, Android и iOS
Тройничок: Selenide для Web, Android и iOSТройничок: Selenide для Web, Android и iOS
Тройничок: Selenide для Web, Android и iOSAndrei Solntsev
 
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 codesAravindharamanan S
 
Windows ストアーアプリで SQLite を使ってみよう
Windows ストアーアプリで SQLite を使ってみようWindows ストアーアプリで SQLite を使ってみよう
Windows ストアーアプリで SQLite を使ってみようShinichiAoyagi
 
Роман Иовлев «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#»SpbDotNet Community
 
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 MAXRobert Nyman
 
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.pdfShaiAlmog1
 
Introduction to Spring Boot.pdf
Introduction to Spring Boot.pdfIntroduction to Spring Boot.pdf
Introduction to Spring Boot.pdfShaiAlmog1
 

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

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

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

Key Features Of Token Development (1).pptx
Key  Features Of Token  Development (1).pptxKey  Features Of Token  Development (1).pptx
Key Features Of Token Development (1).pptxLBM Solutions
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Patryk Bandurski
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slidespraypatel2
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxMalak Abu Hammad
 
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 Nanonetsnaman860154
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsMark Billinghurst
 
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 MenDelhi Call girls
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Scott Keck-Warren
 
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersEnhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersThousandEyes
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationRidwan Fadjar
 
Making_way_through_DLL_hollowing_inspite_of_CFG_by_Debjeet Banerjee.pptx
Making_way_through_DLL_hollowing_inspite_of_CFG_by_Debjeet Banerjee.pptxMaking_way_through_DLL_hollowing_inspite_of_CFG_by_Debjeet Banerjee.pptx
Making_way_through_DLL_hollowing_inspite_of_CFG_by_Debjeet Banerjee.pptxnull - The Open Security Community
 
Hyderabad Call Girls Khairatabad ✨ 7001305949 ✨ Cheap Price Your Budget
Hyderabad Call Girls Khairatabad ✨ 7001305949 ✨ Cheap Price Your BudgetHyderabad Call Girls Khairatabad ✨ 7001305949 ✨ Cheap Price Your Budget
Hyderabad Call Girls Khairatabad ✨ 7001305949 ✨ Cheap Price Your BudgetEnjoy Anytime
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesSinan KOZAK
 
Artificial intelligence in the post-deep learning era
Artificial intelligence in the post-deep learning eraArtificial intelligence in the post-deep learning era
Artificial intelligence in the post-deep learning eraDeakin University
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure servicePooja Nehwal
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsEnterprise Knowledge
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationMichael W. Hawkins
 

Recently uploaded (20)

Key Features Of Token Development (1).pptx
Key  Features Of Token  Development (1).pptxKey  Features Of Token  Development (1).pptx
Key Features Of Token Development (1).pptx
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slides
 
Vulnerability_Management_GRC_by Sohang Sengupta.pptx
Vulnerability_Management_GRC_by Sohang Sengupta.pptxVulnerability_Management_GRC_by Sohang Sengupta.pptx
Vulnerability_Management_GRC_by Sohang Sengupta.pptx
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptx
 
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
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR Systems
 
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
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024
 
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersEnhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 Presentation
 
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptxE-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
 
Making_way_through_DLL_hollowing_inspite_of_CFG_by_Debjeet Banerjee.pptx
Making_way_through_DLL_hollowing_inspite_of_CFG_by_Debjeet Banerjee.pptxMaking_way_through_DLL_hollowing_inspite_of_CFG_by_Debjeet Banerjee.pptx
Making_way_through_DLL_hollowing_inspite_of_CFG_by_Debjeet Banerjee.pptx
 
Hyderabad Call Girls Khairatabad ✨ 7001305949 ✨ Cheap Price Your Budget
Hyderabad Call Girls Khairatabad ✨ 7001305949 ✨ Cheap Price Your BudgetHyderabad Call Girls Khairatabad ✨ 7001305949 ✨ Cheap Price Your Budget
Hyderabad Call Girls Khairatabad ✨ 7001305949 ✨ Cheap Price Your Budget
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen Frames
 
Artificial intelligence in the post-deep learning era
Artificial intelligence in the post-deep learning eraArtificial intelligence in the post-deep learning era
Artificial intelligence in the post-deep learning era
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 

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