SlideShare une entreprise Scribd logo
1  sur  107
Télécharger pour lire hors ligne
Front-end test automation
with HtmlElements -
faster development,
easier support
  Artem Koshelev
  QA Team Lead
                            1
Artem Koshelev

QA Team Lead




artkoshelev@yandex-team.ru
twitter: @art_koshelev




                             2
3
4
5
6
7
8
9
10
11
12
public class HomePageTest {
     ! @Test
     ! public void testSearchResults() {
     ! ! WebDriver driver = new FirefoxDriver();

     !   !   driver.get(“http://market.yandex.ru/”);
     !   !   driver.findElement(By.css(“input#search-input”))
     !   !   ! .sendKeys(“чикипибарум”);
     !   !   driver.findElement(By.css(“td.b-search__button”))
     !   !   ! .click();

     !   ! assertThat(“Не найдено что ничего не найдено”,
     !   ! driver.findElement(By.css(“p.no-found”)).getText(),
     !   ! is(“Заданным условиям не соответствует ни один товар”));
     !   }

13
public class HomePageTest {
     ! @Test
     ! public void testSearchResults() {
     ! ! WebDriver driver = new FirefoxDriver();

     !   !   driver.get(“http://market.yandex.ru/”);
     !   !   driver.findElement(By.css(“input#search-input”))
     !   !   ! .sendKeys(“чикипибарум”);
     !   !   driver.findElement(By.css(“td.b-search__button”))
     !   !   ! .click();

     !   ! assertThat(“Не найдено что ничего не найдено”,
     !   ! driver.findElement(By.css(“p.no-found”)).getText(),
     !   ! is(“Заданным условиям не соответствует ни один товар”));
     !   }

14
public class HomePageTest {
     ! @Test
     ! public void testSearchResults() {
     ! ! WebDriver driver = new FirefoxDriver();

     !   !   driver.get(“http://market.yandex.ru/”);
     !   !   driver.findElement(By.css(“input#search-input”))
     !   !   ! .sendKeys(“чикипибарум”);
     !   !   driver.findElement(By.css(“td.b-search__button”))
     !   !   ! .click();

     !   ! assertThat(“Не найдено что ничего не найдено”,
     !   ! driver.findElement(By.css(“p.no-found”)).getText(),
     !   ! is(“Заданным условиям не соответствует ни один товар”));
     !   }

15
public class HomePageTest {
     ! @Test
     ! public void testSearchResults() {
     ! ! WebDriver driver = new FirefoxDriver();

     !   !   driver.get(“http://market.yandex.ru/”);
     !   !   driver.findElement(By.css(“input#search-input”))
     !   !   ! .sendKeys(“чикипибарум”);
     !   !   driver.findElement(By.css(“td.b-search__button”))
     !   !   ! .click();

     !   ! assertThat(“Не найдено что ничего не найдено”,
     !   ! driver.findElement(By.css(“p.no-found”)).getText(),
     !   ! is(“Заданным условиям не соответствует ни один товар”));
     !   }

16
public class HomePageTest {
     ! @Test
     ! public void testSearchResults() {
     ! ! WebDriver driver = new FirefoxDriver();

     !   !   driver.get(“http://market.yandex.ru/”);
     !   !   driver.findElement(By.css(“input#search-input”))
     !   !   ! .sendKeys(“чикипибарум”);
     !   !   driver.findElement(By.css(“td.b-search__button”))
     !   !   ! .click();

     !   ! assertThat(“Не найдено что ничего не найдено”,
     !   ! driver.findElement(By.css(“p.no-found”)).getText(),
     !   ! is(“Заданным условиям не соответствует ни один товар”));
     !   }

17
public class HomePageTest {
     ! @Test
     ! public void testSearchResults() {
     ! ! WebDriver driver = new FirefoxDriver();

     !   !   driver.get(“http://market.yandex.ru/”);
     !   !   driver.findElement(By.css(“input#search-input”))
     !   !   ! .sendKeys(“чикипибарум”);
     !   !   driver.findElement(By.css(“td.b-search__button”))
     !   !   ! .click();

     !   ! assertThat(“Не найдено что ничего не найдено”,
     !   ! driver.findElement(By.css(“p.no-found”)).getText(),
     !   ! is(“Заданным условиям не соответствует ни один товар”));
     !   }

18
19
20
21
22
23
public class HomePage extends PageObject {
     ! private WebDriver driver;

     ! @FindBy(css = “input#search-input”)
     ! private WebElement searchInput;

     ! @FindBy(css = “td.b-search__button”)
     ! private WebElement searchButton;

     ! public HomePage(WebDriver driver) {
     ! ! return PageFactory.initElements(driver, this.class);
     ! }
     ……



24
public class HomePage extends PageObject {
     ! private WebDriver driver;

     ! @FindBy(css = “input#search-input”)
     ! private WebElement searchInput;

     ! @FindBy(css = “td.b-search__button”)
     ! private WebElement searchButton;

     ! public HomePage(WebDriver driver) {
     ! ! return PageFactory.initElements(driver, this.class);
     ! }
     ……



25
public class HomePage extends PageObject {
     ! private WebDriver driver;

     ! @FindBy(css = “input#search-input”)
     ! private WebElement searchInput;

     ! @FindBy(css = “td.b-search__button”)
     ! private WebElement searchButton;

     ! public HomePage(WebDriver driver) {
     ! ! return PageFactory.initElements(driver, this.class);
     ! }
     ……



26
public class HomePage extends PageObject {
     ! private WebDriver driver;

     ! @FindBy(css = “input#search-input”)
     ! private WebElement searchInput;

     ! @FindBy(css = “td.b-search__button”)
     ! private WebElement searchButton;

     ! public HomePage(WebDriver driver) {
     ! ! return PageFactory.initElements(driver, this.class);
     ! }
     ……



27
public class HomePage extends PageObject {
     ! ……

     !   public SearchResultsPage lookFor(String item) {
     !   ! searchInput.type(item);
     !   ! searchButton.click();
     !   ! return new SearchResultsPage(driver);
     !   }

     !   public CatalogModelsPage clickOnElectronicLink() {
     !   ! electronikLink.click();
     !   ! return new CatalogModelsPage(driver);
     !   }

     ……!

28
public class HomePage extends PageObject {
     ! ……

     !   public SearchResultsPage lookFor(String item) {
     !   ! searchInput.type(item);
     !   ! searchButton.click();
     !   ! return new SearchResultsPage(driver);
     !   }

     !   public CatalogModelsPage clickOnElectronicLink() {
     !   ! electronikLink.click();
     !   ! return new CatalogModelsPage(driver);
     !   }

     ……!

29
public class HomePage extends PageObject {
     ! ……

     !   public SearchResultsPage lookFor(String item) {
     !   ! searchInput.type(item);
     !   ! searchButton.click();
     !   ! return new SearchResultsPage(driver);
     !   }

     !   public CatalogModelsPage clickOnElectronicLink() {
     !   ! electronikLink.click();
     !   ! return new CatalogModelsPage(driver);
     !   }

     ……!

30
HomePage onHomePage;
     SearchResultsPage onResultsPage;

     @Test
     public void canSearch() {
     ! onHomePage = new HomePage(driver).open();
     ! onResultsPage = onHomePage.lookFor(“чикипибарум”);

         assertThat(onResultsPage.errorMessage(), !        !
         ! is(“Заданным условиям не соответствует ни один товар.”));
     }




31
HomePage onHomePage;
     SearchResultsPage onResultsPage;

     @Test
     public void canSearch() {
     ! onHomePage = new HomePage(driver).open();
     ! onResultsPage = onHomePage.lookFor(“чикипибарум”);

         assertThat(onResultsPage.errorMessage(), !        !
         ! is(“Заданным условиям не соответствует ни один товар.”));
     }




32
HomePage onHomePage;
     SearchResultsPage onResultsPage;

     @Test
     public void canSearch() {
     ! onHomePage = new HomePage(driver).open();
     ! onResultsPage = onHomePage.lookFor(“чикипибарум”);

         assertThat(onResultsPage.errorMessage(), !        !
         ! is(“Заданным условиям не соответствует ни один товар.”));
     }




33
34
35
36
UserSteps user;

     @Test
     public void canSearch() {
       user.onHomePage();
       user.looksFor(“чикипибарум”);

         user.shouldSeeErrorMessage();
     }




37
38
39
public class HomePage extends PageObject {

     ! @FindBy(css = “input#search-input”)
     ! private WebElement searchInput;

     ! @FindBy(css = “td.b-search__button”)
     ! private WebElement searchButton;




40
public class HomePage extends PageObject {

     ! @FindBy(css = “input#search-input”)
     ! private WebElement searchInput;

     ! @FindBy(css = “td.b-search__button”)
     ! private WebElement searchButton;




41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
@Block(@FindBy(…))
     public class SearchArrow extends HtmlElement {
     ! ! @FindBy(…)
     ! ! private WebElement searchInput;

     ! ! @FindBy(…)
     ! ! private WebElement searchButton;
     }



62
@Block(@FindBy(…))
     public class SearchArrow extends HtmlElement {
     ! ! @FindBy(…)
     ! ! private WebElement searchInput;

     ! ! @FindBy(…)
     ! ! private WebElement searchButton;
     }



63
@Block(@FindBy(…))
     public class SearchArrow extends HtmlElement {
     ! ! @FindBy(…)
     ! ! private WebElement searchInput;

     ! ! @FindBy(…)
     ! ! private WebElement searchButton;
     }



64
@Block(@FindBy(…))
     public class SearchArrow extends HtmlElement {
     ! ! @FindBy(…)
     ! ! private WebElement searchInput;

     ! ! @FindBy(…)
     ! ! private WebElement searchButton;
     }



65
66
@Block(@FindBy(…))
     public class SearchBlock extends HtmlElement {

     ! ! private SearchArrow arrow;
     ! ! private SearchTabs tabs;

     }




67
public class HomePage extends PageObject {


     ! ! public SearchBlock searchBlock;

     }




68
public class HomePage extends PageObject {

         @FindBy(xpath = “//another_locator”)
     ! ! public SearchBlock arrow;

     }




69
70
@Block(@FindBy(…))
     public class SearchArrow extends HtmlElement {
     ! ! @FindBy(…)
     ! ! private WebElement searchInput;

     ! ! @FindBy(…)
     ! ! private WebElement searchButton;
     }




71
@Block(@FindBy(…))
     public class SearchArrow extends HtmlElement {
     ! ! @FindBy(…)
     ! ! private TextInput searchInput;

     ! ! @FindBy(…)
     ! ! private Button searchButton;
     }




72
73
74
75
public class Form extends TypifiedElement {

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

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

         ...
     }


76
public class Table extends TypifiedElement {

         public List<WebElement> getHeadings() {}
         public List<List<WebElement>> getRows() {}
         public List<List<WebElement>> getColumns() {}

     }




77
public class Link extends TypifiedElement {

     ! public Link(WebElement wrappedElement) {
     ! ! super(wrappedElement)
     ! }

         ......

     }



78
public class Link extends TypifiedElement {

         ......

     ! public void click() {…}

     ! public String getReference() {…}

     ! public String getText(){…}

     }
79
80
assertThat(actual, Matcher);




81
assertThat(event, is(“Я.Субботник в Риге”));

     assertThat(today,
             isSameDayOfTheWeek(31_jan_2009));

     assertThat(attendies, not(lessThan(100)));




82
assertThat(seasonsControlForm, exists());

     assertThat(seasonsControlForm,
           hasText(«Seasons shift setup»));

     assertThat(enableSeasonsShift, isSelected());

     assertThat(currentSeason, hasSelectedOption(
           hasText(«Spring»)));

83
assertThat(seasonsControlForm, exists());

     assertThat(seasonsControlForm,
           hasText(«Seasons shift setup»));

     assertThat(enableSeasonsShift, isSelected());

     assertThat(currentSeason, hasSelectedOption(
           hasText(«Spring»)));

84
assertThat(seasonsControlForm, exists());

     assertThat(seasonsControlForm,
           hasText(«Seasons shift setup»));

     assertThat(enableSeasonsShift, isSelected());

     assertThat(currentSeason, hasSelectedOption(
           hasText(«Spring»)));

85
assertThat(seasonsControlForm, exists());

     assertThat(seasonsControlForm,
           hasText(«Seasons shift setup»));

     assertThat(enableSeasonsShift, isSelected());

     assertThat(currentSeason, hasSelectedOption(
           hasText(«Spring»)));

86
assertThat(element, should(exists()).
                    whileWaitingUntil(timeout));

     assertThat(element, should(exists()).
                    after(pageRefresh(driver));

     assertThat(humanRace, should(not(exists())).
                    inCase(zombieApocalypse));

     assertThat(chuckNorris, should(exists()).
                    inCase(zombieApocalypse));

87
assertThat(element, should(exists()).
                    whileWaitingUntil(timeout));

     assertThat(element, should(exists()).
                    after(pageRefresh(driver));

     assertThat(humanRace, should(not(exists())).
                    inCase(zombieApocalypse));

     assertThat(chuckNorris, should(exists()).
                    inCase(zombieApocalypse));

88
assertThat(element, should(exists()).
                    whileWaitingUntil(timeout));

     assertThat(element, should(exists()).
                    after(pageRefresh(driver));

     assertThat(humanRace, should(not(exists())).
                    inCase(zombieApocalypse));

     assertThat(chuckNorris, should(exists()).
                    inCase(zombieApocalypse));

89
assertThat(element, should(exists()).
                    whileWaitingUntil(timeout));

     assertThat(element, should(exists()).
                    after(pageRefresh(driver));

     assertThat(humanRace, should(not(exists())).
                    inCase(zombieApocalypse));

     assertThat(chuckNorris, should(exists()).
                    inCase(zombieApocalypse));

90
assertThat(element, should(exists()).
                    whileWaitingUntil(timeout));

     assertThat(element, should(exists()).
                    after(pageRefresh(driver));

     assertThat(humanRace, should(not(exists())).
                    inCase(zombieApocalypse));

     assertThat(chuckNorris, should(exists()).
                    inCase(zombieApocalypse));

91
assertThat(element, should(exists()).
                    whileWaitingUntil(timeout));

     assertThat(element, should(exists()).
                    after(pageRefresh(driver));

     assertThat(humanRace, should(not(exists())).
                    inCase(zombieApocalypse));

     assertThat(chuckNorris, should(exists()).
                    inCase(zombieApocalypse));

92
public void shouldSeeSuggest(Matcher mchr) {
         assertThat(
               onSearchPage().getSuggest(), mchr);
     }

     @Test
     public void popularSuggests() {
         user.opensSearchPage();
         user.typesInSearch(«riga»);
         user.shouldSeeSuggest(
           everyItem(hasText(startsWith(«riga»))));
         user.shouldSeeSuggest(
93
           hasItem(hasText(«riga weather»)));
public void shouldSeeSuggest(Matcher mchr) {
         assertThat(
               onSearchPage().getSuggest(), mchr);
     }

     @Test
     public void popularSuggests() {
         user.opensSearchPage();
         user.typesInSearch(«riga»);
         user.shouldSeeSuggest(
           everyItem(hasText(startsWith(«riga»))));
         user.shouldSeeSuggest(
94
           hasItem(hasText(«riga weather»)));
public void shouldSeeSuggest(Matcher mchr) {
         assertThat(
               onSearchPage().getSuggest(), mchr);
     }

     @Test
     public void popularSuggests() {
         user.opensSearchPage();
         user.typesInSearch(«riga»);
         user.shouldSeeSuggest(
           everyItem(hasText(startsWith(«riga»))));
         user.shouldSeeSuggest(
95
           hasItem(hasText(«riga weather»)));
public void shouldSeeSuggest(Matcher mchr) {
         assertThat(
               onSearchPage().getSuggest(), mchr);
     }

     @Test
     public void popularSuggests() {
         user.opensSearchPage();
         user.typesInSearch(«riga»);
         user.shouldSeeSuggest(
           everyItem(hasText(startsWith(«riga»))));
         user.shouldSeeSuggest(
96
           hasItem(hasText(«riga weather»)));
public void shouldSeeSuggest(Matcher mchr) {
         assertThat(
               onSearchPage().getSuggest(), mchr);
     }

     @Test
     public void popularSuggests() {
         user.opensSearchPage();
         user.typesInSearch(«riga»);
         user.shouldSeeSuggest(
           everyItem(hasText(startsWith(«riga»))));
         user.shouldSeeSuggest(
97
           hasItem(hasText(«riga weather»)));
98
<dependency>
         <groupId>
           ru.yandex.qatools.htmlelements
         </groupId>

        <artifactId>
          htmlelements-java
        </artifactId>

        <version>1.9</version>

     </dependency>
99
100
101
102
103
104
105
http://bit.ly/htmlelements   http://bit.ly/yqahegg

                   qa-tools@yandex-team.ru
106
Artem Koshelev

QA Team Lead




artkoshelev@yandex-team.ru
twitter: @art_koshelev




                             107

Contenu connexe

En vedette

Big data: current technology scope.
Big data: current technology scope.Big data: current technology scope.
Big data: current technology scope.Roman Nikitchenko
 
"The Human Face of Big Data", Crystal Valentine, VP of Technology Strategy at...
"The Human Face of Big Data", Crystal Valentine, VP of Technology Strategy at..."The Human Face of Big Data", Crystal Valentine, VP of Technology Strategy at...
"The Human Face of Big Data", Crystal Valentine, VP of Technology Strategy at...Dataconomy Media
 
Editorial Writing 101
Editorial Writing 101Editorial Writing 101
Editorial Writing 101Ken_Writer
 
Предсказание оттока игроков из World of Tanks
Предсказание оттока игроков из World of TanksПредсказание оттока игроков из World of Tanks
Предсказание оттока игроков из World of TanksYandex
 

En vedette (6)

Big data: current technology scope.
Big data: current technology scope.Big data: current technology scope.
Big data: current technology scope.
 
Big Data Technology
Big Data TechnologyBig Data Technology
Big Data Technology
 
"The Human Face of Big Data", Crystal Valentine, VP of Technology Strategy at...
"The Human Face of Big Data", Crystal Valentine, VP of Technology Strategy at..."The Human Face of Big Data", Crystal Valentine, VP of Technology Strategy at...
"The Human Face of Big Data", Crystal Valentine, VP of Technology Strategy at...
 
Column writing
Column writingColumn writing
Column writing
 
Editorial Writing 101
Editorial Writing 101Editorial Writing 101
Editorial Writing 101
 
Предсказание оттока игроков из World of Tanks
Предсказание оттока игроков из World of TanksПредсказание оттока игроков из World of Tanks
Предсказание оттока игроков из World of Tanks
 

Plus de Yandex

Как принять/организовать работу по поисковой оптимизации сайта, Сергей Царик,...
Как принять/организовать работу по поисковой оптимизации сайта, Сергей Царик,...Как принять/организовать работу по поисковой оптимизации сайта, Сергей Царик,...
Как принять/организовать работу по поисковой оптимизации сайта, Сергей Царик,...Yandex
 
Структурированные данные, Юлия Тихоход, лекция в Школе вебмастеров Яндекса
Структурированные данные, Юлия Тихоход, лекция в Школе вебмастеров ЯндексаСтруктурированные данные, Юлия Тихоход, лекция в Школе вебмастеров Яндекса
Структурированные данные, Юлия Тихоход, лекция в Школе вебмастеров ЯндексаYandex
 
Представление сайта в поиске, Сергей Лысенко, лекция в Школе вебмастеров Яндекса
Представление сайта в поиске, Сергей Лысенко, лекция в Школе вебмастеров ЯндексаПредставление сайта в поиске, Сергей Лысенко, лекция в Школе вебмастеров Яндекса
Представление сайта в поиске, Сергей Лысенко, лекция в Школе вебмастеров ЯндексаYandex
 
Плохие методы продвижения сайта, Екатерины Гладких, лекция в Школе вебмастеро...
Плохие методы продвижения сайта, Екатерины Гладких, лекция в Школе вебмастеро...Плохие методы продвижения сайта, Екатерины Гладких, лекция в Школе вебмастеро...
Плохие методы продвижения сайта, Екатерины Гладких, лекция в Школе вебмастеро...Yandex
 
Основные принципы ранжирования, Сергей Царик и Антон Роменский, лекция в Школ...
Основные принципы ранжирования, Сергей Царик и Антон Роменский, лекция в Школ...Основные принципы ранжирования, Сергей Царик и Антон Роменский, лекция в Школ...
Основные принципы ранжирования, Сергей Царик и Антон Роменский, лекция в Школ...Yandex
 
Основные принципы индексирования сайта, Александр Смирнов, лекция в Школе веб...
Основные принципы индексирования сайта, Александр Смирнов, лекция в Школе веб...Основные принципы индексирования сайта, Александр Смирнов, лекция в Школе веб...
Основные принципы индексирования сайта, Александр Смирнов, лекция в Школе веб...Yandex
 
Мобильное приложение: как и зачем, Александр Лукин, лекция в Школе вебмастеро...
Мобильное приложение: как и зачем, Александр Лукин, лекция в Школе вебмастеро...Мобильное приложение: как и зачем, Александр Лукин, лекция в Школе вебмастеро...
Мобильное приложение: как и зачем, Александр Лукин, лекция в Школе вебмастеро...Yandex
 
Сайты на мобильных устройствах, Олег Ножичкин, лекция в Школе вебмастеров Янд...
Сайты на мобильных устройствах, Олег Ножичкин, лекция в Школе вебмастеров Янд...Сайты на мобильных устройствах, Олег Ножичкин, лекция в Школе вебмастеров Янд...
Сайты на мобильных устройствах, Олег Ножичкин, лекция в Школе вебмастеров Янд...Yandex
 
Качественная аналитика сайта, Юрий Батиевский, лекция в Школе вебмастеров Янд...
Качественная аналитика сайта, Юрий Батиевский, лекция в Школе вебмастеров Янд...Качественная аналитика сайта, Юрий Батиевский, лекция в Школе вебмастеров Янд...
Качественная аналитика сайта, Юрий Батиевский, лекция в Школе вебмастеров Янд...Yandex
 
Что можно и что нужно измерять на сайте, Петр Аброськин, лекция в Школе вебма...
Что можно и что нужно измерять на сайте, Петр Аброськин, лекция в Школе вебма...Что можно и что нужно измерять на сайте, Петр Аброськин, лекция в Школе вебма...
Что можно и что нужно измерять на сайте, Петр Аброськин, лекция в Школе вебма...Yandex
 
Как правильно поставить ТЗ на создание сайта, Алексей Бородкин, лекция в Школ...
Как правильно поставить ТЗ на создание сайта, Алексей Бородкин, лекция в Школ...Как правильно поставить ТЗ на создание сайта, Алексей Бородкин, лекция в Школ...
Как правильно поставить ТЗ на создание сайта, Алексей Бородкин, лекция в Школ...Yandex
 
Как защитить свой сайт, Пётр Волков, лекция в Школе вебмастеров
Как защитить свой сайт, Пётр Волков, лекция в Школе вебмастеровКак защитить свой сайт, Пётр Волков, лекция в Школе вебмастеров
Как защитить свой сайт, Пётр Волков, лекция в Школе вебмастеровYandex
 
Как правильно составить структуру сайта, Дмитрий Сатин, лекция в Школе вебмас...
Как правильно составить структуру сайта, Дмитрий Сатин, лекция в Школе вебмас...Как правильно составить структуру сайта, Дмитрий Сатин, лекция в Школе вебмас...
Как правильно составить структуру сайта, Дмитрий Сатин, лекция в Школе вебмас...Yandex
 
Технические особенности создания сайта, Дмитрий Васильева, лекция в Школе веб...
Технические особенности создания сайта, Дмитрий Васильева, лекция в Школе веб...Технические особенности создания сайта, Дмитрий Васильева, лекция в Школе веб...
Технические особенности создания сайта, Дмитрий Васильева, лекция в Школе веб...Yandex
 
Конструкторы для отдельных элементов сайта, Елена Першина, лекция в Школе веб...
Конструкторы для отдельных элементов сайта, Елена Першина, лекция в Школе веб...Конструкторы для отдельных элементов сайта, Елена Першина, лекция в Школе веб...
Конструкторы для отдельных элементов сайта, Елена Першина, лекция в Школе веб...Yandex
 
Контент для интернет-магазинов, Катерина Ерошина, лекция в Школе вебмастеров ...
Контент для интернет-магазинов, Катерина Ерошина, лекция в Школе вебмастеров ...Контент для интернет-магазинов, Катерина Ерошина, лекция в Школе вебмастеров ...
Контент для интернет-магазинов, Катерина Ерошина, лекция в Школе вебмастеров ...Yandex
 
Как написать хороший текст для сайта, Катерина Ерошина, лекция в Школе вебмас...
Как написать хороший текст для сайта, Катерина Ерошина, лекция в Школе вебмас...Как написать хороший текст для сайта, Катерина Ерошина, лекция в Школе вебмас...
Как написать хороший текст для сайта, Катерина Ерошина, лекция в Школе вебмас...Yandex
 
Usability и дизайн - как не помешать пользователю, Алексей Иванов, лекция в Ш...
Usability и дизайн - как не помешать пользователю, Алексей Иванов, лекция в Ш...Usability и дизайн - как не помешать пользователю, Алексей Иванов, лекция в Ш...
Usability и дизайн - как не помешать пользователю, Алексей Иванов, лекция в Ш...Yandex
 
Cайт. Зачем он и каким должен быть, Алексей Иванов, лекция в Школе вебмастеро...
Cайт. Зачем он и каким должен быть, Алексей Иванов, лекция в Школе вебмастеро...Cайт. Зачем он и каким должен быть, Алексей Иванов, лекция в Школе вебмастеро...
Cайт. Зачем он и каким должен быть, Алексей Иванов, лекция в Школе вебмастеро...Yandex
 
Эталонное описание фильма на основе десятков дубликатов
Эталонное описание фильма на основе десятков дубликатовЭталонное описание фильма на основе десятков дубликатов
Эталонное описание фильма на основе десятков дубликатовYandex
 

Plus de Yandex (20)

Как принять/организовать работу по поисковой оптимизации сайта, Сергей Царик,...
Как принять/организовать работу по поисковой оптимизации сайта, Сергей Царик,...Как принять/организовать работу по поисковой оптимизации сайта, Сергей Царик,...
Как принять/организовать работу по поисковой оптимизации сайта, Сергей Царик,...
 
Структурированные данные, Юлия Тихоход, лекция в Школе вебмастеров Яндекса
Структурированные данные, Юлия Тихоход, лекция в Школе вебмастеров ЯндексаСтруктурированные данные, Юлия Тихоход, лекция в Школе вебмастеров Яндекса
Структурированные данные, Юлия Тихоход, лекция в Школе вебмастеров Яндекса
 
Представление сайта в поиске, Сергей Лысенко, лекция в Школе вебмастеров Яндекса
Представление сайта в поиске, Сергей Лысенко, лекция в Школе вебмастеров ЯндексаПредставление сайта в поиске, Сергей Лысенко, лекция в Школе вебмастеров Яндекса
Представление сайта в поиске, Сергей Лысенко, лекция в Школе вебмастеров Яндекса
 
Плохие методы продвижения сайта, Екатерины Гладких, лекция в Школе вебмастеро...
Плохие методы продвижения сайта, Екатерины Гладких, лекция в Школе вебмастеро...Плохие методы продвижения сайта, Екатерины Гладких, лекция в Школе вебмастеро...
Плохие методы продвижения сайта, Екатерины Гладких, лекция в Школе вебмастеро...
 
Основные принципы ранжирования, Сергей Царик и Антон Роменский, лекция в Школ...
Основные принципы ранжирования, Сергей Царик и Антон Роменский, лекция в Школ...Основные принципы ранжирования, Сергей Царик и Антон Роменский, лекция в Школ...
Основные принципы ранжирования, Сергей Царик и Антон Роменский, лекция в Школ...
 
Основные принципы индексирования сайта, Александр Смирнов, лекция в Школе веб...
Основные принципы индексирования сайта, Александр Смирнов, лекция в Школе веб...Основные принципы индексирования сайта, Александр Смирнов, лекция в Школе веб...
Основные принципы индексирования сайта, Александр Смирнов, лекция в Школе веб...
 
Мобильное приложение: как и зачем, Александр Лукин, лекция в Школе вебмастеро...
Мобильное приложение: как и зачем, Александр Лукин, лекция в Школе вебмастеро...Мобильное приложение: как и зачем, Александр Лукин, лекция в Школе вебмастеро...
Мобильное приложение: как и зачем, Александр Лукин, лекция в Школе вебмастеро...
 
Сайты на мобильных устройствах, Олег Ножичкин, лекция в Школе вебмастеров Янд...
Сайты на мобильных устройствах, Олег Ножичкин, лекция в Школе вебмастеров Янд...Сайты на мобильных устройствах, Олег Ножичкин, лекция в Школе вебмастеров Янд...
Сайты на мобильных устройствах, Олег Ножичкин, лекция в Школе вебмастеров Янд...
 
Качественная аналитика сайта, Юрий Батиевский, лекция в Школе вебмастеров Янд...
Качественная аналитика сайта, Юрий Батиевский, лекция в Школе вебмастеров Янд...Качественная аналитика сайта, Юрий Батиевский, лекция в Школе вебмастеров Янд...
Качественная аналитика сайта, Юрий Батиевский, лекция в Школе вебмастеров Янд...
 
Что можно и что нужно измерять на сайте, Петр Аброськин, лекция в Школе вебма...
Что можно и что нужно измерять на сайте, Петр Аброськин, лекция в Школе вебма...Что можно и что нужно измерять на сайте, Петр Аброськин, лекция в Школе вебма...
Что можно и что нужно измерять на сайте, Петр Аброськин, лекция в Школе вебма...
 
Как правильно поставить ТЗ на создание сайта, Алексей Бородкин, лекция в Школ...
Как правильно поставить ТЗ на создание сайта, Алексей Бородкин, лекция в Школ...Как правильно поставить ТЗ на создание сайта, Алексей Бородкин, лекция в Школ...
Как правильно поставить ТЗ на создание сайта, Алексей Бородкин, лекция в Школ...
 
Как защитить свой сайт, Пётр Волков, лекция в Школе вебмастеров
Как защитить свой сайт, Пётр Волков, лекция в Школе вебмастеровКак защитить свой сайт, Пётр Волков, лекция в Школе вебмастеров
Как защитить свой сайт, Пётр Волков, лекция в Школе вебмастеров
 
Как правильно составить структуру сайта, Дмитрий Сатин, лекция в Школе вебмас...
Как правильно составить структуру сайта, Дмитрий Сатин, лекция в Школе вебмас...Как правильно составить структуру сайта, Дмитрий Сатин, лекция в Школе вебмас...
Как правильно составить структуру сайта, Дмитрий Сатин, лекция в Школе вебмас...
 
Технические особенности создания сайта, Дмитрий Васильева, лекция в Школе веб...
Технические особенности создания сайта, Дмитрий Васильева, лекция в Школе веб...Технические особенности создания сайта, Дмитрий Васильева, лекция в Школе веб...
Технические особенности создания сайта, Дмитрий Васильева, лекция в Школе веб...
 
Конструкторы для отдельных элементов сайта, Елена Першина, лекция в Школе веб...
Конструкторы для отдельных элементов сайта, Елена Першина, лекция в Школе веб...Конструкторы для отдельных элементов сайта, Елена Першина, лекция в Школе веб...
Конструкторы для отдельных элементов сайта, Елена Першина, лекция в Школе веб...
 
Контент для интернет-магазинов, Катерина Ерошина, лекция в Школе вебмастеров ...
Контент для интернет-магазинов, Катерина Ерошина, лекция в Школе вебмастеров ...Контент для интернет-магазинов, Катерина Ерошина, лекция в Школе вебмастеров ...
Контент для интернет-магазинов, Катерина Ерошина, лекция в Школе вебмастеров ...
 
Как написать хороший текст для сайта, Катерина Ерошина, лекция в Школе вебмас...
Как написать хороший текст для сайта, Катерина Ерошина, лекция в Школе вебмас...Как написать хороший текст для сайта, Катерина Ерошина, лекция в Школе вебмас...
Как написать хороший текст для сайта, Катерина Ерошина, лекция в Школе вебмас...
 
Usability и дизайн - как не помешать пользователю, Алексей Иванов, лекция в Ш...
Usability и дизайн - как не помешать пользователю, Алексей Иванов, лекция в Ш...Usability и дизайн - как не помешать пользователю, Алексей Иванов, лекция в Ш...
Usability и дизайн - как не помешать пользователю, Алексей Иванов, лекция в Ш...
 
Cайт. Зачем он и каким должен быть, Алексей Иванов, лекция в Школе вебмастеро...
Cайт. Зачем он и каким должен быть, Алексей Иванов, лекция в Школе вебмастеро...Cайт. Зачем он и каким должен быть, Алексей Иванов, лекция в Школе вебмастеро...
Cайт. Зачем он и каким должен быть, Алексей Иванов, лекция в Школе вебмастеро...
 
Эталонное описание фильма на основе десятков дубликатов
Эталонное описание фильма на основе десятков дубликатовЭталонное описание фильма на основе десятков дубликатов
Эталонное описание фильма на основе десятков дубликатов
 

Артём Кошелев "Тестирование фронтенда с HtmlElements: разработка быстрее, поддержка – проще"

  • 1. Front-end test automation with HtmlElements - faster development, easier support Artem Koshelev QA Team Lead 1
  • 2. Artem Koshelev QA Team Lead artkoshelev@yandex-team.ru twitter: @art_koshelev 2
  • 3. 3
  • 4. 4
  • 5. 5
  • 6. 6
  • 7. 7
  • 8. 8
  • 9. 9
  • 10. 10
  • 11. 11
  • 12. 12
  • 13. public class HomePageTest { ! @Test ! public void testSearchResults() { ! ! WebDriver driver = new FirefoxDriver(); ! ! driver.get(“http://market.yandex.ru/”); ! ! driver.findElement(By.css(“input#search-input”)) ! ! ! .sendKeys(“чикипибарум”); ! ! driver.findElement(By.css(“td.b-search__button”)) ! ! ! .click(); ! ! assertThat(“Не найдено что ничего не найдено”, ! ! driver.findElement(By.css(“p.no-found”)).getText(), ! ! is(“Заданным условиям не соответствует ни один товар”)); ! } 13
  • 14. public class HomePageTest { ! @Test ! public void testSearchResults() { ! ! WebDriver driver = new FirefoxDriver(); ! ! driver.get(“http://market.yandex.ru/”); ! ! driver.findElement(By.css(“input#search-input”)) ! ! ! .sendKeys(“чикипибарум”); ! ! driver.findElement(By.css(“td.b-search__button”)) ! ! ! .click(); ! ! assertThat(“Не найдено что ничего не найдено”, ! ! driver.findElement(By.css(“p.no-found”)).getText(), ! ! is(“Заданным условиям не соответствует ни один товар”)); ! } 14
  • 15. public class HomePageTest { ! @Test ! public void testSearchResults() { ! ! WebDriver driver = new FirefoxDriver(); ! ! driver.get(“http://market.yandex.ru/”); ! ! driver.findElement(By.css(“input#search-input”)) ! ! ! .sendKeys(“чикипибарум”); ! ! driver.findElement(By.css(“td.b-search__button”)) ! ! ! .click(); ! ! assertThat(“Не найдено что ничего не найдено”, ! ! driver.findElement(By.css(“p.no-found”)).getText(), ! ! is(“Заданным условиям не соответствует ни один товар”)); ! } 15
  • 16. public class HomePageTest { ! @Test ! public void testSearchResults() { ! ! WebDriver driver = new FirefoxDriver(); ! ! driver.get(“http://market.yandex.ru/”); ! ! driver.findElement(By.css(“input#search-input”)) ! ! ! .sendKeys(“чикипибарум”); ! ! driver.findElement(By.css(“td.b-search__button”)) ! ! ! .click(); ! ! assertThat(“Не найдено что ничего не найдено”, ! ! driver.findElement(By.css(“p.no-found”)).getText(), ! ! is(“Заданным условиям не соответствует ни один товар”)); ! } 16
  • 17. public class HomePageTest { ! @Test ! public void testSearchResults() { ! ! WebDriver driver = new FirefoxDriver(); ! ! driver.get(“http://market.yandex.ru/”); ! ! driver.findElement(By.css(“input#search-input”)) ! ! ! .sendKeys(“чикипибарум”); ! ! driver.findElement(By.css(“td.b-search__button”)) ! ! ! .click(); ! ! assertThat(“Не найдено что ничего не найдено”, ! ! driver.findElement(By.css(“p.no-found”)).getText(), ! ! is(“Заданным условиям не соответствует ни один товар”)); ! } 17
  • 18. public class HomePageTest { ! @Test ! public void testSearchResults() { ! ! WebDriver driver = new FirefoxDriver(); ! ! driver.get(“http://market.yandex.ru/”); ! ! driver.findElement(By.css(“input#search-input”)) ! ! ! .sendKeys(“чикипибарум”); ! ! driver.findElement(By.css(“td.b-search__button”)) ! ! ! .click(); ! ! assertThat(“Не найдено что ничего не найдено”, ! ! driver.findElement(By.css(“p.no-found”)).getText(), ! ! is(“Заданным условиям не соответствует ни один товар”)); ! } 18
  • 19. 19
  • 20. 20
  • 21. 21
  • 22. 22
  • 23. 23
  • 24. public class HomePage extends PageObject { ! private WebDriver driver; ! @FindBy(css = “input#search-input”) ! private WebElement searchInput; ! @FindBy(css = “td.b-search__button”) ! private WebElement searchButton; ! public HomePage(WebDriver driver) { ! ! return PageFactory.initElements(driver, this.class); ! } …… 24
  • 25. public class HomePage extends PageObject { ! private WebDriver driver; ! @FindBy(css = “input#search-input”) ! private WebElement searchInput; ! @FindBy(css = “td.b-search__button”) ! private WebElement searchButton; ! public HomePage(WebDriver driver) { ! ! return PageFactory.initElements(driver, this.class); ! } …… 25
  • 26. public class HomePage extends PageObject { ! private WebDriver driver; ! @FindBy(css = “input#search-input”) ! private WebElement searchInput; ! @FindBy(css = “td.b-search__button”) ! private WebElement searchButton; ! public HomePage(WebDriver driver) { ! ! return PageFactory.initElements(driver, this.class); ! } …… 26
  • 27. public class HomePage extends PageObject { ! private WebDriver driver; ! @FindBy(css = “input#search-input”) ! private WebElement searchInput; ! @FindBy(css = “td.b-search__button”) ! private WebElement searchButton; ! public HomePage(WebDriver driver) { ! ! return PageFactory.initElements(driver, this.class); ! } …… 27
  • 28. public class HomePage extends PageObject { ! …… ! public SearchResultsPage lookFor(String item) { ! ! searchInput.type(item); ! ! searchButton.click(); ! ! return new SearchResultsPage(driver); ! } ! public CatalogModelsPage clickOnElectronicLink() { ! ! electronikLink.click(); ! ! return new CatalogModelsPage(driver); ! } ……! 28
  • 29. public class HomePage extends PageObject { ! …… ! public SearchResultsPage lookFor(String item) { ! ! searchInput.type(item); ! ! searchButton.click(); ! ! return new SearchResultsPage(driver); ! } ! public CatalogModelsPage clickOnElectronicLink() { ! ! electronikLink.click(); ! ! return new CatalogModelsPage(driver); ! } ……! 29
  • 30. public class HomePage extends PageObject { ! …… ! public SearchResultsPage lookFor(String item) { ! ! searchInput.type(item); ! ! searchButton.click(); ! ! return new SearchResultsPage(driver); ! } ! public CatalogModelsPage clickOnElectronicLink() { ! ! electronikLink.click(); ! ! return new CatalogModelsPage(driver); ! } ……! 30
  • 31. HomePage onHomePage; SearchResultsPage onResultsPage; @Test public void canSearch() { ! onHomePage = new HomePage(driver).open(); ! onResultsPage = onHomePage.lookFor(“чикипибарум”); assertThat(onResultsPage.errorMessage(), ! ! ! is(“Заданным условиям не соответствует ни один товар.”)); } 31
  • 32. HomePage onHomePage; SearchResultsPage onResultsPage; @Test public void canSearch() { ! onHomePage = new HomePage(driver).open(); ! onResultsPage = onHomePage.lookFor(“чикипибарум”); assertThat(onResultsPage.errorMessage(), ! ! ! is(“Заданным условиям не соответствует ни один товар.”)); } 32
  • 33. HomePage onHomePage; SearchResultsPage onResultsPage; @Test public void canSearch() { ! onHomePage = new HomePage(driver).open(); ! onResultsPage = onHomePage.lookFor(“чикипибарум”); assertThat(onResultsPage.errorMessage(), ! ! ! is(“Заданным условиям не соответствует ни один товар.”)); } 33
  • 34. 34
  • 35. 35
  • 36. 36
  • 37. UserSteps user; @Test public void canSearch() { user.onHomePage(); user.looksFor(“чикипибарум”); user.shouldSeeErrorMessage(); } 37
  • 38. 38
  • 39. 39
  • 40. public class HomePage extends PageObject { ! @FindBy(css = “input#search-input”) ! private WebElement searchInput; ! @FindBy(css = “td.b-search__button”) ! private WebElement searchButton; 40
  • 41. public class HomePage extends PageObject { ! @FindBy(css = “input#search-input”) ! private WebElement searchInput; ! @FindBy(css = “td.b-search__button”) ! private WebElement searchButton; 41
  • 42. 42
  • 43. 43
  • 44. 44
  • 45. 45
  • 46. 46
  • 47. 47
  • 48. 48
  • 49. 49
  • 50. 50
  • 51. 51
  • 52. 52
  • 53. 53
  • 54. 54
  • 55. 55
  • 56. 56
  • 57. 57
  • 58. 58
  • 59. 59
  • 60. 60
  • 61. 61
  • 62. @Block(@FindBy(…)) public class SearchArrow extends HtmlElement { ! ! @FindBy(…) ! ! private WebElement searchInput; ! ! @FindBy(…) ! ! private WebElement searchButton; } 62
  • 63. @Block(@FindBy(…)) public class SearchArrow extends HtmlElement { ! ! @FindBy(…) ! ! private WebElement searchInput; ! ! @FindBy(…) ! ! private WebElement searchButton; } 63
  • 64. @Block(@FindBy(…)) public class SearchArrow extends HtmlElement { ! ! @FindBy(…) ! ! private WebElement searchInput; ! ! @FindBy(…) ! ! private WebElement searchButton; } 64
  • 65. @Block(@FindBy(…)) public class SearchArrow extends HtmlElement { ! ! @FindBy(…) ! ! private WebElement searchInput; ! ! @FindBy(…) ! ! private WebElement searchButton; } 65
  • 66. 66
  • 67. @Block(@FindBy(…)) public class SearchBlock extends HtmlElement { ! ! private SearchArrow arrow; ! ! private SearchTabs tabs; } 67
  • 68. public class HomePage extends PageObject { ! ! public SearchBlock searchBlock; } 68
  • 69. public class HomePage extends PageObject { @FindBy(xpath = “//another_locator”) ! ! public SearchBlock arrow; } 69
  • 70. 70
  • 71. @Block(@FindBy(…)) public class SearchArrow extends HtmlElement { ! ! @FindBy(…) ! ! private WebElement searchInput; ! ! @FindBy(…) ! ! private WebElement searchButton; } 71
  • 72. @Block(@FindBy(…)) public class SearchArrow extends HtmlElement { ! ! @FindBy(…) ! ! private TextInput searchInput; ! ! @FindBy(…) ! ! private Button searchButton; } 72
  • 73. 73
  • 74. 74
  • 75. 75
  • 76. public class Form extends TypifiedElement { public void fill(Map<String, Object> data) {...} public <T> void fill(T bean, Converter beanToMapConverter) {...} ... } 76
  • 77. public class Table extends TypifiedElement { public List<WebElement> getHeadings() {} public List<List<WebElement>> getRows() {} public List<List<WebElement>> getColumns() {} } 77
  • 78. public class Link extends TypifiedElement { ! public Link(WebElement wrappedElement) { ! ! super(wrappedElement) ! } ...... } 78
  • 79. public class Link extends TypifiedElement { ...... ! public void click() {…} ! public String getReference() {…} ! public String getText(){…} } 79
  • 80. 80
  • 82. assertThat(event, is(“Я.Субботник в Риге”)); assertThat(today, isSameDayOfTheWeek(31_jan_2009)); assertThat(attendies, not(lessThan(100))); 82
  • 83. assertThat(seasonsControlForm, exists()); assertThat(seasonsControlForm, hasText(«Seasons shift setup»)); assertThat(enableSeasonsShift, isSelected()); assertThat(currentSeason, hasSelectedOption( hasText(«Spring»))); 83
  • 84. assertThat(seasonsControlForm, exists()); assertThat(seasonsControlForm, hasText(«Seasons shift setup»)); assertThat(enableSeasonsShift, isSelected()); assertThat(currentSeason, hasSelectedOption( hasText(«Spring»))); 84
  • 85. assertThat(seasonsControlForm, exists()); assertThat(seasonsControlForm, hasText(«Seasons shift setup»)); assertThat(enableSeasonsShift, isSelected()); assertThat(currentSeason, hasSelectedOption( hasText(«Spring»))); 85
  • 86. assertThat(seasonsControlForm, exists()); assertThat(seasonsControlForm, hasText(«Seasons shift setup»)); assertThat(enableSeasonsShift, isSelected()); assertThat(currentSeason, hasSelectedOption( hasText(«Spring»))); 86
  • 87. assertThat(element, should(exists()). whileWaitingUntil(timeout)); assertThat(element, should(exists()). after(pageRefresh(driver)); assertThat(humanRace, should(not(exists())). inCase(zombieApocalypse)); assertThat(chuckNorris, should(exists()). inCase(zombieApocalypse)); 87
  • 88. assertThat(element, should(exists()). whileWaitingUntil(timeout)); assertThat(element, should(exists()). after(pageRefresh(driver)); assertThat(humanRace, should(not(exists())). inCase(zombieApocalypse)); assertThat(chuckNorris, should(exists()). inCase(zombieApocalypse)); 88
  • 89. assertThat(element, should(exists()). whileWaitingUntil(timeout)); assertThat(element, should(exists()). after(pageRefresh(driver)); assertThat(humanRace, should(not(exists())). inCase(zombieApocalypse)); assertThat(chuckNorris, should(exists()). inCase(zombieApocalypse)); 89
  • 90. assertThat(element, should(exists()). whileWaitingUntil(timeout)); assertThat(element, should(exists()). after(pageRefresh(driver)); assertThat(humanRace, should(not(exists())). inCase(zombieApocalypse)); assertThat(chuckNorris, should(exists()). inCase(zombieApocalypse)); 90
  • 91. assertThat(element, should(exists()). whileWaitingUntil(timeout)); assertThat(element, should(exists()). after(pageRefresh(driver)); assertThat(humanRace, should(not(exists())). inCase(zombieApocalypse)); assertThat(chuckNorris, should(exists()). inCase(zombieApocalypse)); 91
  • 92. assertThat(element, should(exists()). whileWaitingUntil(timeout)); assertThat(element, should(exists()). after(pageRefresh(driver)); assertThat(humanRace, should(not(exists())). inCase(zombieApocalypse)); assertThat(chuckNorris, should(exists()). inCase(zombieApocalypse)); 92
  • 93. public void shouldSeeSuggest(Matcher mchr) { assertThat( onSearchPage().getSuggest(), mchr); } @Test public void popularSuggests() { user.opensSearchPage(); user.typesInSearch(«riga»); user.shouldSeeSuggest( everyItem(hasText(startsWith(«riga»)))); user.shouldSeeSuggest( 93 hasItem(hasText(«riga weather»)));
  • 94. public void shouldSeeSuggest(Matcher mchr) { assertThat( onSearchPage().getSuggest(), mchr); } @Test public void popularSuggests() { user.opensSearchPage(); user.typesInSearch(«riga»); user.shouldSeeSuggest( everyItem(hasText(startsWith(«riga»)))); user.shouldSeeSuggest( 94 hasItem(hasText(«riga weather»)));
  • 95. public void shouldSeeSuggest(Matcher mchr) { assertThat( onSearchPage().getSuggest(), mchr); } @Test public void popularSuggests() { user.opensSearchPage(); user.typesInSearch(«riga»); user.shouldSeeSuggest( everyItem(hasText(startsWith(«riga»)))); user.shouldSeeSuggest( 95 hasItem(hasText(«riga weather»)));
  • 96. public void shouldSeeSuggest(Matcher mchr) { assertThat( onSearchPage().getSuggest(), mchr); } @Test public void popularSuggests() { user.opensSearchPage(); user.typesInSearch(«riga»); user.shouldSeeSuggest( everyItem(hasText(startsWith(«riga»)))); user.shouldSeeSuggest( 96 hasItem(hasText(«riga weather»)));
  • 97. public void shouldSeeSuggest(Matcher mchr) { assertThat( onSearchPage().getSuggest(), mchr); } @Test public void popularSuggests() { user.opensSearchPage(); user.typesInSearch(«riga»); user.shouldSeeSuggest( everyItem(hasText(startsWith(«riga»)))); user.shouldSeeSuggest( 97 hasItem(hasText(«riga weather»)));
  • 98. 98
  • 99. <dependency> <groupId> ru.yandex.qatools.htmlelements </groupId> <artifactId> htmlelements-java </artifactId> <version>1.9</version> </dependency> 99
  • 100. 100
  • 101. 101
  • 102. 102
  • 103. 103
  • 104. 104
  • 105. 105
  • 106. http://bit.ly/htmlelements http://bit.ly/yqahegg qa-tools@yandex-team.ru 106
  • 107. Artem Koshelev QA Team Lead artkoshelev@yandex-team.ru twitter: @art_koshelev 107