SlideShare a Scribd company logo
1 of 48
Download to read offline
За пределами
              PageObject

               Дмитрий Жарий




atdays.com
Давайте познакомимся!




Дима Жарий
atdays.com      #atdays        2
Аджендиум…                                [OK]
=================================================

1. Вам не нужен PageObject
2. Вам нужен PageObject
3. PageObject – это паттерн, шаблон… ИДЕЯ!
4. Статический PageObject
5. Динамический PageObject
6. За пределами:
   • Паттерн «Цепочка ответственности»
       и .Invoke()
   • Интерфейс IHaveExpectedControls
   • Наследование в тестах


atdays.com                   #atdays                3
ВАМ ДЕЙСТВИТЕЛЬНО НУЖЕН
    PAGE OBJECT?

atdays.com    #atdays         4
Нет. Если у вас парочка
               несложных тестов
public void Wikipedia_Smart_Search_Test()
{
    RemoteWebDriver driver = new InternetExplorerDriver();

     driver.Navigate()
           .GoToUrl("http://en.wikipedia.org/wiki/Main_Page");

     driver.FindElementByCssSelector(@"div#simpleSearch")
           .SendKeys("Webdriver Selenium");

     Assert.AreEqual("http://en.wiki {...} Driver"
                    , driver.Url);
}




atdays.com                   #atdays                             5
Нет. Если у вас несколько
               сложных тестов




atdays.com          #atdays          6
Ведь код можно улучшить




atdays.com      #atdays         7
Как улучшить?
     Вынести часто используемый функционал
     в общедоступные методы
     Отформатировать код
     Добавить комментарии
      driver.FindElement(By.XPath("//a[text()='Log On']"))
      .Click();


      // Click on the Log On link.
      var logOnLink = driver.FindElement(
                             By.XPath("//a[text()='Log On']"));
      logOnLink.Click();

atdays.com                    #atdays                             8
И, если у вас все под
                 контролем…




atdays.com            #atdays        9
ВАМ НЕ НУЖЕН PAGE OBJECT!


atdays.com     #atdays          10
var ddlMonthSelect =
   new
   SelectElement(driver.Fin
                                        Прости, ня! 
   dElementByName(@"EXPIRYD
   ATE_MM"));
               var
   ddlYearSelect = new
   SelectElement(driver.Fin
   dElementByName(@"EXPIRYD
   ATE_YY"));
               var
   txtSecurityCode =
   driver.FindElementByName
   (@"CVV");
               var
   btnContinue =
   driver.FindElementById("
   btnSubmit");


   ddlMonthSelect.SelectByT
   ext("05");

   ddlYearSelect.SelectByTe
   xt("15");

atdays.com                    #atdays               11
Когда приходит Хаос…
     "Тест-простыней" становится слишком
     много

     В коде не разобраться без пол-литру

     На поддержку уходит уж слишком много
     времени

     Легче всё переписать заново

     Начинаете ненавидеть разработчиков,
     которые вынесли div из span

atdays.com             #atdays              12
PageObject – он как книжная
              полка

  Pages

      LoginPage

       → Login(name, passwd)


      MainPage
       → LogOut()
       → GotoProjects()
       → GotoUserProfile()
       → Search(text)
atdays.com                     #atdays   13
PAGE OBJECT – ОН ГИБКИЙ

atdays.com     #atdays        14
PageObject – это:


    Концентрация
   на языке задачи,
а не на языке решения

atdays.com          #atdays      15
PageObject – главная цель

     Обеспечить хранение локаторов в отдельном
     классе

     Обеспечить повторное использование локаторов
     и/или действий над страницей без дублирования
     кода

     Обеспечить слой абстракции от «драйвера» так,
     чтобы в тестах не использовались физические
     элементы идентификации
     элементов управления приложением



atdays.com               #atdays                     16
А выглядит всё вот так



                      MainPage
                                      Т
                                      Е
                                      С
                        Create        Т
                       Account
                         Page
atdays.com            #atdays             17
Демо!




atdays.com    #atdays   18
ЧТО ЭТО БЫЛО? –
    СТАТИЧЕСКИЙ PAGE OBJECT!

atdays.com     #atdays         19
Позитив 01: Тест стал
                       читабелен
public static RemoteWebDriver Driver { get { return WebBrowser.Driver; } }


[TestMethod]
public void Donate_test_static()
{
    MyPages.MainPage.Open();
    MyPages.MainPage.GoToDonatePage();
    MyPages.DonatePage.Donate_50_UAH_Using_Debit_Card();
    MyPages.DonationPaymentsForm.FillDonationForm
        (
            firstName : "Vasya",
            lastName : "Pupkin",
            securityCode : "555"

             );
    // CUT
}

atdays.com                          #atdays                                  20
Позитив 2: Удобная «точка
            входа» в страницы




atdays.com          #atdays          21
Позитив 3: Driver стал доступен
               отовсюду!
public static class WebBrowser
{
    public static RemoteWebDriver _driver = null;

    public static RemoteWebDriver Driver
    {
        get
        {
             _driver = _driver ?? new InternetExplorerDriver();
             return _driver;
        }
    }
}
                  public static RemoteWebDriver Driver {
                         get { return WebBrowser.Driver; }
                  }
atdays.com                    #atdays                             22
И еще раз о позитиве
     Теперь жизнь браузера (драйвера)
     контролирует класс WebBrowser.

     Текущий драйвер доступен из любого
     участка кода

     Любая страница доступна из MyPages.*

     Наш тест теперь помещается на один
     экран монитора

atdays.com            #atdays               23
Ограничения статического
              класса в C#
                                          class   static class
  Наследоваться                           можно   нельзя
  Породить много разных                   можно   нельзя
  Инициализировать параметрами
                                          можно   нельзя
  через конструктор
                                                  полностью нельзя. Очень
  Завалить                                можно   живучие

  Присвоить переменной                    можно   нельзя

  Передать как параметр другому методу    можно   нельзя

  Реализовать интерфейс                   можно   нельзя
  Использовать статические методы         можно   можно

  Использовать статические поля           можно   можно

  Инициализировать при помощи Webdriver           нельзя "из коробки",
                                          можно
  PageFactory                                     нужно написать свою фабрику

atdays.com                            #atdays                                   24
ГИБКОСТЬ – ЭТО ВАЖНО.
    PAGE OBJECT КАК OBJECT

atdays.com     #atdays       25
Тест не изменился! Спасибо,
              MyPages




atdays.com      #atdays           26
Изменения в MyPages
public static class MyPages
{
    public static MainPage MainPage
    {
        get { return new MainPage();}
    }

     public static DonatePage DonatePage
     {
         get { return new DonatePage(); }
     }

}
atdays.com             #atdays              27
Новая структура проекта

     Object               Static




atdays.com      #atdays            28
AbstractPageBase

public abstract class AbstractPageBase
{
    public RemoteWebDriver Driver
    {
        get { return WebBrowser.Driver; }
    }
}




atdays.com           #atdays                29
PaymentResultPage
public class PaymentResultPage : AbstractPageBase
{
    public void WaitUntilExists()
    {
        WebDriverWait wait = new WebDriverWait(Driver,
                                TimeSpan.FromSeconds(30));
        wait.Until(ExpectedConditions.TitleContains(
                   @"Donate-error - Payments"));
    }

     public string GetResultHeaderText()
     {
         var lblFirstHeader = Driver.
                              FindElementById(@"firstHeading");
         return lblFirstHeader.Text;
     }
}
atdays.com                   #atdays                              30
Changelog
     Появился базовый класс
     AbstractPageBase
     Из MyPages.* можно по-прежнему
     получить любую страницу
     Декларация страниц была вынесена из
     MyPages в отдельные файлы
     Мы лишились ограничений статических
     классов
     ТЕПЕРЬ НАС НЕ ОСТАНОВИТЬ!

atdays.com           #atdays               31
Статический/Динамический –
     разница в перспективах




  Статический
atdays.com
                     Динамический
                #atdays             32
ПАТТЕРНЫ (РЕЦЕПТЫ)
    И ИНТЕРФЕЙСЫ (РОЛИ)

atdays.com     #atdays    33
http://bash.im/quote/420885




xxx: тема письма в рабочей почте
      " RE: FW: FW: RE: RE: FW: RE: СРОЧНО!!!!!!"

yyy: Вот это проблема структурных
    организаций


          ЦЕПОЧКА ОТВЕТСТВЕННОСТИ
          /CHAIN OF RESPONSIBILITY/

  atdays.com                  #atdays           34
Chain of Responsibility

                 ??                 ?


               ???    Цепочка ответственности

                       ????


atdays.com                #atdays               35
Iinvokable

public interface IInvokable
{
    void Invoke();
    bool Exists();
}
                 Invoke – вызвать

                 Invokable – то, что можно вызвать

                 I invokable – Я вызываемый(-оя, -ое)!

atdays.com      #atdays                                  36
НужнаяPage.Invoke():
НужнаяPage.Invoke():

Если я уже Exists() – то вот она я!

Если я не Exists(), то я сделаю:
  ПредыдущаяPage.Invoke()
  Потом что-то нажму – вот она я!


                                 Donation
              Donate
                                 Payments
               Page
                                   Form
atdays.com                  #atdays         37
Что дает нам Iinvokable?
     Любую страницу можно вызвать с
     параметрами по умолчанию


     var page = MyPages.
                PaymentResultErrorInvalidCreditCard;

     page.Invoke();




atdays.com                 #atdays                     38
Что дает нам Iinvokable?
     Передать страницу как параметр метода
public void TestThatPageExists(IInvokable page)
{
    page.Invoke();
    Assert.IsTrue(page.Exists());
}

[TestMethod]
public void Test_PaymentResultErrorInvalidCreditCard()
{

    TestThatPageExists(
                  MyPages.PaymentResultErrnvalidCreditCard
                    );
}
atdays.com                   #atdays                         39
Что дает нам Iinvokable?
     Если нужная страница уже открыта (после
     предыдущего теста ) – она будет использована
     повторно

     public void Invoke()
     {
         if (Exists() == false)
         {
             var mainPage = MyPages.MainPage;
             mainPage.Invoke();
             mainPage.GoToDonatePage();
         }
     }


atdays.com                   #atdays                40
I HAVE EXPECTED CONTROLS

atdays.com      #atdays        41
Сышишь, а есть какиета
                  кантролы?
 public interface IHaveExpectedControls : IInvokable
 {
     List<IWebElement> GetExpectedControls();
 }




               .Invoke()
               .Exists()
               .GetExpectedControls()
atdays.com                #atdays                      42
Get Expected Controls
                  (PageObject)
public class DonatePage : AbstractPageBase, IHaveExpectedControls
{
    [FindsBy(Using=@"input[name='amount'][value='50']",
             How = How.CssSelector)]
     public IWebElement rbtnDonate50;

     [FindsBy(Using=@"input[value='Donate by credit/debit card']",
             How = How.CssSelector)]
     public IWebElement btnMakeDonation;

     public List<IWebElement> GetExpectedControls()
     {
         return new List<IWebElement>()
         {
             rbtnDonate50,
             btnMakeDonation
         };
     }
 atdays.com                           #atdays                        43
Позволяет писать
             универсальные тесты
public virtual IHaveExpectedControls CurrentPage
{
       get { return null; }
}

[TestMethod]
public void TestExpectedControls()
{
    CurrentPage.Invoke();

     var expectedControls = CurrentPage.GetExpectedControls();
     foreach (var expectedControl in expectedControls)
     {
              Assert.IsTrue(expectedControl.Displayed);
     }

}
atdays.com                   #atdays                             44
Авто-тесты для авто-тестов?


                           Легкие тесты, которые:
                           1. Открывают каждую страницу
                           2. Проверяет каждый важный
                              элемент страницы




             Основной тест-набор



atdays.com                #atdays                         45
Та да да дам!




atdays.com        #atdays    46
Спасибы:
     За то, что доклад состоялся:
        Спасибо Вам!

     За Invoke()
             Виктору Линчевскому
             Леониду Артемьеву

     Помощь в подготовке доклада:
             Михаил Поляруш
             Андрей Ребров
atdays.com                 #atdays   47
Я не прощаюсь, я говорю: до
              свидания!




Дима Жарий
atdays.com       #atdays           48

More Related Content

What's hot

Встроенное приложение «Управление документами» в версии 5.0
Встроенное приложение «Управление документами» в версии 5.0Встроенное приложение «Управление документами» в версии 5.0
Встроенное приложение «Управление документами» в версии 5.0
Docsvision
 
МРТ для данных, Frontend Conf 2016
МРТ для данных, Frontend Conf 2016МРТ для данных, Frontend Conf 2016
МРТ для данных, Frontend Conf 2016
Anastasia Goryacheva
 
За пределами PageObject
За пределами PageObjectЗа пределами PageObject
За пределами PageObject
automated-testing.info
 
basis.js - почему я не бросил разрабатывать свой фреймворк
basis.js - почему я не бросил разрабатывать свой фреймворкbasis.js - почему я не бросил разрабатывать свой фреймворк
basis.js - почему я не бросил разрабатывать свой фреймворк
Roman Dvornov
 
Фундаментальные основы разработки под iOS. Павел Тайкало
Фундаментальные основы разработки под iOS. Павел ТайкалоФундаментальные основы разработки под iOS. Павел Тайкало
Фундаментальные основы разработки под iOS. Павел Тайкало
Stanfy
 
Knockout.JS на примере 2ГИС-Онлайн
Knockout.JS на примере 2ГИС-ОнлайнKnockout.JS на примере 2ГИС-Онлайн
Knockout.JS на примере 2ГИС-Онлайн
DevDay
 
Алексей Бережной — «jQuery»
Алексей Бережной — «jQuery»Алексей Бережной — «jQuery»
Алексей Бережной — «jQuery»
Yandex
 
CodeFest 2013. Никонов Г. — Как мы разрабатываем приложения для Windows Phone...
CodeFest 2013. Никонов Г. — Как мы разрабатываем приложения для Windows Phone...CodeFest 2013. Никонов Г. — Как мы разрабатываем приложения для Windows Phone...
CodeFest 2013. Никонов Г. — Как мы разрабатываем приложения для Windows Phone...
CodeFest
 

What's hot (20)

Встроенное приложение «Управление документами» в версии 5.0
Встроенное приложение «Управление документами» в версии 5.0Встроенное приложение «Управление документами» в версии 5.0
Встроенное приложение «Управление документами» в версии 5.0
 
МРТ для данных, Frontend Conf 2016
МРТ для данных, Frontend Conf 2016МРТ для данных, Frontend Conf 2016
МРТ для данных, Frontend Conf 2016
 
За пределами PageObject
За пределами PageObjectЗа пределами PageObject
За пределами PageObject
 
Basis.js – «под капотом»
Basis.js – «под капотом»Basis.js – «под капотом»
Basis.js – «под капотом»
 
basis.js - почему я не бросил разрабатывать свой фреймворк
basis.js - почему я не бросил разрабатывать свой фреймворкbasis.js - почему я не бросил разрабатывать свой фреймворк
basis.js - почему я не бросил разрабатывать свой фреймворк
 
55+1 прием для улучшения Javascript-кода / Татьяна Бабич (Simbirsoft)
55+1 прием для улучшения Javascript-кода / Татьяна Бабич (Simbirsoft)55+1 прием для улучшения Javascript-кода / Татьяна Бабич (Simbirsoft)
55+1 прием для улучшения Javascript-кода / Татьяна Бабич (Simbirsoft)
 
Фундаментальные основы разработки под iOS. Павел Тайкало
Фундаментальные основы разработки под iOS. Павел ТайкалоФундаментальные основы разработки под iOS. Павел Тайкало
Фундаментальные основы разработки под iOS. Павел Тайкало
 
Баба Яга против!
Баба Яга против!Баба Яга против!
Баба Яга против!
 
Жизнь в изоляции
Жизнь в изоляцииЖизнь в изоляции
Жизнь в изоляции
 
JavaScript Базовый. Занятие 09.
JavaScript Базовый. Занятие 09.JavaScript Базовый. Занятие 09.
JavaScript Базовый. Занятие 09.
 
C# Web. Занятие 13.
C# Web. Занятие 13.C# Web. Занятие 13.
C# Web. Занятие 13.
 
Knockout.JS на примере 2ГИС-Онлайн
Knockout.JS на примере 2ГИС-ОнлайнKnockout.JS на примере 2ГИС-Онлайн
Knockout.JS на примере 2ГИС-Онлайн
 
Vue.js - реактивный фронтенд фреймворк для людей
Vue.js - реактивный фронтенд фреймворк для людейVue.js - реактивный фронтенд фреймворк для людей
Vue.js - реактивный фронтенд фреймворк для людей
 
#3 "Webpack и Vue.JS: Создание больших приложений и их расширение" Кирилл Кай...
#3 "Webpack и Vue.JS: Создание больших приложений и их расширение" Кирилл Кай...#3 "Webpack и Vue.JS: Создание больших приложений и их расширение" Кирилл Кай...
#3 "Webpack и Vue.JS: Создание больших приложений и их расширение" Кирилл Кай...
 
Kranonit s16 (python). dmitry furzenko
Kranonit s16 (python). dmitry furzenkoKranonit s16 (python). dmitry furzenko
Kranonit s16 (python). dmitry furzenko
 
Инструменты разные нужны, инструменты разные важны
Инструменты разные нужны, инструменты разные важныИнструменты разные нужны, инструменты разные важны
Инструменты разные нужны, инструменты разные важны
 
'The best practices' by KONSTANTIN KULAKSYZ at OdessaJS'2020
'The best practices' by KONSTANTIN KULAKSYZ at OdessaJS'2020'The best practices' by KONSTANTIN KULAKSYZ at OdessaJS'2020
'The best practices' by KONSTANTIN KULAKSYZ at OdessaJS'2020
 
Алексей Бережной — «jQuery»
Алексей Бережной — «jQuery»Алексей Бережной — «jQuery»
Алексей Бережной — «jQuery»
 
Basis.js - почему я не бросил разрабатывать свой фреймворк (extended)
Basis.js - почему я не бросил разрабатывать свой фреймворк (extended)Basis.js - почему я не бросил разрабатывать свой фреймворк (extended)
Basis.js - почему я не бросил разрабатывать свой фреймворк (extended)
 
CodeFest 2013. Никонов Г. — Как мы разрабатываем приложения для Windows Phone...
CodeFest 2013. Никонов Г. — Как мы разрабатываем приложения для Windows Phone...CodeFest 2013. Никонов Г. — Как мы разрабатываем приложения для Windows Phone...
CodeFest 2013. Никонов Г. — Как мы разрабатываем приложения для Windows Phone...
 

Viewers also liked

Confet&QA Обходные пути в автоматизированном тестировании
Confet&QA Обходные пути в автоматизированном тестированииConfet&QA Обходные пути в автоматизированном тестировании
Confet&QA Обходные пути в автоматизированном тестировании
Dmytro Zharii
 
Cовременный контроль качества: давай сделаем это по-быстрому...
Cовременный контроль качества: давай сделаем это по-быстрому...Cовременный контроль качества: давай сделаем это по-быстрому...
Cовременный контроль качества: давай сделаем это по-быстрому...
Igor Khrol
 
автоматизация Flex приложений с помощью selenium rc
автоматизация Flex приложений с помощью selenium rcавтоматизация Flex приложений с помощью selenium rc
автоматизация Flex приложений с помощью selenium rc
Igor Khrol
 
Web driver история одной миграции
Web driver   история одной миграцииWeb driver   история одной миграции
Web driver история одной миграции
Igor Khrol
 
Тесты в стиле BDD на C# (Подходы и инструменты; SpecFlow, BDDfy)
Тесты в стиле BDD на C# (Подходы и инструменты; SpecFlow, BDDfy)Тесты в стиле BDD на C# (Подходы и инструменты; SpecFlow, BDDfy)
Тесты в стиле BDD на C# (Подходы и инструменты; SpecFlow, BDDfy)
Dmytro Zharii
 
Типичные ошибки начинающих писать тесты на WebDriver
Типичные ошибки начинающих писать тесты на WebDriverТипичные ошибки начинающих писать тесты на WebDriver
Типичные ошибки начинающих писать тесты на WebDriver
Igor Khrol
 

Viewers also liked (12)

Confet&QA Обходные пути в автоматизированном тестировании
Confet&QA Обходные пути в автоматизированном тестированииConfet&QA Обходные пути в автоматизированном тестировании
Confet&QA Обходные пути в автоматизированном тестировании
 
Cовременный контроль качества: давай сделаем это по-быстрому...
Cовременный контроль качества: давай сделаем это по-быстрому...Cовременный контроль качества: давай сделаем это по-быстрому...
Cовременный контроль качества: давай сделаем это по-быстрому...
 
Правила оформления текста в интерфейсе приложений
Правила оформления текста в интерфейсе приложенийПравила оформления текста в интерфейсе приложений
Правила оформления текста в интерфейсе приложений
 
Повышаем надёжность тестов через JavaScript
Повышаем надёжность тестов через JavaScriptПовышаем надёжность тестов через JavaScript
Повышаем надёжность тестов через JavaScript
 
автоматизация Flex приложений с помощью selenium rc
автоматизация Flex приложений с помощью selenium rcавтоматизация Flex приложений с помощью selenium rc
автоматизация Flex приложений с помощью selenium rc
 
Qa Automation - отбрасываем лишнее и тестируем суть
Qa Automation - отбрасываем лишнее и тестируем сутьQa Automation - отбрасываем лишнее и тестируем суть
Qa Automation - отбрасываем лишнее и тестируем суть
 
Web driver история одной миграции
Web driver   история одной миграцииWeb driver   история одной миграции
Web driver история одной миграции
 
Тесты в стиле BDD на C# (Подходы и инструменты; SpecFlow, BDDfy)
Тесты в стиле BDD на C# (Подходы и инструменты; SpecFlow, BDDfy)Тесты в стиле BDD на C# (Подходы и инструменты; SpecFlow, BDDfy)
Тесты в стиле BDD на C# (Подходы и инструменты; SpecFlow, BDDfy)
 
Grail - CodeFest'2015
Grail - CodeFest'2015Grail - CodeFest'2015
Grail - CodeFest'2015
 
Test Automation Wargaming SQA Days 17
Test Automation Wargaming SQA Days 17Test Automation Wargaming SQA Days 17
Test Automation Wargaming SQA Days 17
 
Типичные ошибки начинающих писать тесты на WebDriver
Типичные ошибки начинающих писать тесты на WebDriverТипичные ошибки начинающих писать тесты на WebDriver
Типичные ошибки начинающих писать тесты на WebDriver
 
Webium: Page Objects in Python
Webium: Page Objects in PythonWebium: Page Objects in Python
Webium: Page Objects in Python
 

Similar to За пределами Page Object. ATDays 2013 Киев. Февраль 2013

Knockoutjs на примере 2ГИС-Онлайн
Knockoutjs на примере 2ГИС-ОнлайнKnockoutjs на примере 2ГИС-Онлайн
Knockoutjs на примере 2ГИС-Онлайн
2ГИС Технологии
 
Easy authcache 2 кеширование для pro родионов игорь
Easy authcache 2   кеширование для pro родионов игорьEasy authcache 2   кеширование для pro родионов игорь
Easy authcache 2 кеширование для pro родионов игорь
drupalconf
 
Эволюция к Behavior Driven Development на примере популярного фреймворка JBehave
Эволюция к Behavior Driven Development на примере популярного фреймворка JBehaveЭволюция к Behavior Driven Development на примере популярного фреймворка JBehave
Эволюция к Behavior Driven Development на примере популярного фреймворка JBehave
Return on Intelligence
 
Иван Карев — Клиентская оптимизация
Иван Карев — Клиентская оптимизацияИван Карев — Клиентская оптимизация
Иван Карев — Клиентская оптимизация
Yandex
 
Easy authcache 2 кэширование для pro. Родионов Игорь
Easy authcache 2   кэширование для pro. Родионов ИгорьEasy authcache 2   кэширование для pro. Родионов Игорь
Easy authcache 2 кэширование для pro. Родионов Игорь
PVasili
 

Similar to За пределами Page Object. ATDays 2013 Киев. Февраль 2013 (20)

Фреймворк для регрессионного тестирования на основе WebDriver
Фреймворк для регрессионного тестирования на основе WebDriverФреймворк для регрессионного тестирования на основе WebDriver
Фреймворк для регрессионного тестирования на основе WebDriver
 
Сергей Константинов — Что интересного готовит нам W3C
Сергей Константинов — Что интересного готовит нам W3CСергей Константинов — Что интересного готовит нам W3C
Сергей Константинов — Что интересного готовит нам W3C
 
Совершенный тестовый фреймворк
Совершенный тестовый фреймворкСовершенный тестовый фреймворк
Совершенный тестовый фреймворк
 
State of the Standardized Web
State of the Standardized WebState of the Standardized Web
State of the Standardized Web
 
webpack: 7 бед - один ответ
webpack: 7 бед - один ответwebpack: 7 бед - один ответ
webpack: 7 бед - один ответ
 
Иван Карев — Клиентская оптимизация
Иван Карев — Клиентская оптимизацияИван Карев — Клиентская оптимизация
Иван Карев — Клиентская оптимизация
 
Knockoutjs на примере 2ГИС-Онлайн
Knockoutjs на примере 2ГИС-ОнлайнKnockoutjs на примере 2ГИС-Онлайн
Knockoutjs на примере 2ГИС-Онлайн
 
Little Service in 2h
Little Service in 2hLittle Service in 2h
Little Service in 2h
 
Николай Сиварев "Приручая сайты"
Николай Сиварев "Приручая сайты"Николай Сиварев "Приручая сайты"
Николай Сиварев "Приручая сайты"
 
Telerik Web aii
Telerik Web aiiTelerik Web aii
Telerik Web aii
 
"Webpack: 7 бед — один ответ" — Денис Измайлов, MoscowJS 17
"Webpack: 7 бед — один ответ" — Денис Измайлов, MoscowJS 17"Webpack: 7 бед — один ответ" — Денис Измайлов, MoscowJS 17
"Webpack: 7 бед — один ответ" — Денис Измайлов, MoscowJS 17
 
Easy authcache 2 кеширование для pro родионов игорь
Easy authcache 2   кеширование для pro родионов игорьEasy authcache 2   кеширование для pro родионов игорь
Easy authcache 2 кеширование для pro родионов игорь
 
The Old New ASP.NET
The Old New ASP.NETThe Old New ASP.NET
The Old New ASP.NET
 
TК°Conf. 10 проблем автоматизации UI и их решение с помощью JDI. Роман Иовлев.
TК°Conf. 10 проблем автоматизации UI и их решение с помощью JDI. Роман Иовлев.TК°Conf. 10 проблем автоматизации UI и их решение с помощью JDI. Роман Иовлев.
TК°Conf. 10 проблем автоматизации UI и их решение с помощью JDI. Роман Иовлев.
 
Эволюция к Behavior Driven Development на примере популярного фреймворка JBehave
Эволюция к Behavior Driven Development на примере популярного фреймворка JBehaveЭволюция к Behavior Driven Development на примере популярного фреймворка JBehave
Эволюция к Behavior Driven Development на примере популярного фреймворка JBehave
 
Что нам стоит DAL построить? Акуляков Артём D2D Just.NET
Что нам стоит DAL построить? Акуляков Артём D2D Just.NETЧто нам стоит DAL построить? Акуляков Артём D2D Just.NET
Что нам стоит DAL построить? Акуляков Артём D2D Just.NET
 
Иван Карев — Клиентская оптимизация
Иван Карев — Клиентская оптимизацияИван Карев — Клиентская оптимизация
Иван Карев — Клиентская оптимизация
 
Easy authcache 2 кэширование для pro. Родионов Игорь
Easy authcache 2   кэширование для pro. Родионов ИгорьEasy authcache 2   кэширование для pro. Родионов Игорь
Easy authcache 2 кэширование для pro. Родионов Игорь
 
2014 Jeeconf - Geb Spock
2014 Jeeconf - Geb Spock2014 Jeeconf - Geb Spock
2014 Jeeconf - Geb Spock
 
iOS and Android Mobile Test Automation
iOS and Android Mobile Test AutomationiOS and Android Mobile Test Automation
iOS and Android Mobile Test Automation
 

За пределами Page Object. ATDays 2013 Киев. Февраль 2013

  • 1. За пределами PageObject Дмитрий Жарий atdays.com
  • 3. Аджендиум… [OK] ================================================= 1. Вам не нужен PageObject 2. Вам нужен PageObject 3. PageObject – это паттерн, шаблон… ИДЕЯ! 4. Статический PageObject 5. Динамический PageObject 6. За пределами: • Паттерн «Цепочка ответственности» и .Invoke() • Интерфейс IHaveExpectedControls • Наследование в тестах atdays.com #atdays 3
  • 4. ВАМ ДЕЙСТВИТЕЛЬНО НУЖЕН PAGE OBJECT? atdays.com #atdays 4
  • 5. Нет. Если у вас парочка несложных тестов public void Wikipedia_Smart_Search_Test() { RemoteWebDriver driver = new InternetExplorerDriver(); driver.Navigate() .GoToUrl("http://en.wikipedia.org/wiki/Main_Page"); driver.FindElementByCssSelector(@"div#simpleSearch") .SendKeys("Webdriver Selenium"); Assert.AreEqual("http://en.wiki {...} Driver" , driver.Url); } atdays.com #atdays 5
  • 6. Нет. Если у вас несколько сложных тестов atdays.com #atdays 6
  • 7. Ведь код можно улучшить atdays.com #atdays 7
  • 8. Как улучшить? Вынести часто используемый функционал в общедоступные методы Отформатировать код Добавить комментарии driver.FindElement(By.XPath("//a[text()='Log On']")) .Click(); // Click on the Log On link. var logOnLink = driver.FindElement( By.XPath("//a[text()='Log On']")); logOnLink.Click(); atdays.com #atdays 8
  • 9. И, если у вас все под контролем… atdays.com #atdays 9
  • 10. ВАМ НЕ НУЖЕН PAGE OBJECT! atdays.com #atdays 10
  • 11. var ddlMonthSelect = new SelectElement(driver.Fin Прости, ня!  dElementByName(@"EXPIRYD ATE_MM")); var ddlYearSelect = new SelectElement(driver.Fin dElementByName(@"EXPIRYD ATE_YY")); var txtSecurityCode = driver.FindElementByName (@"CVV"); var btnContinue = driver.FindElementById(" btnSubmit"); ddlMonthSelect.SelectByT ext("05"); ddlYearSelect.SelectByTe xt("15"); atdays.com #atdays 11
  • 12. Когда приходит Хаос… "Тест-простыней" становится слишком много В коде не разобраться без пол-литру На поддержку уходит уж слишком много времени Легче всё переписать заново Начинаете ненавидеть разработчиков, которые вынесли div из span atdays.com #atdays 12
  • 13. PageObject – он как книжная полка Pages LoginPage → Login(name, passwd) MainPage → LogOut() → GotoProjects() → GotoUserProfile() → Search(text) atdays.com #atdays 13
  • 14. PAGE OBJECT – ОН ГИБКИЙ atdays.com #atdays 14
  • 15. PageObject – это: Концентрация на языке задачи, а не на языке решения atdays.com #atdays 15
  • 16. PageObject – главная цель Обеспечить хранение локаторов в отдельном классе Обеспечить повторное использование локаторов и/или действий над страницей без дублирования кода Обеспечить слой абстракции от «драйвера» так, чтобы в тестах не использовались физические элементы идентификации элементов управления приложением atdays.com #atdays 16
  • 17. А выглядит всё вот так MainPage Т Е С Create Т Account Page atdays.com #atdays 17
  • 18. Демо! atdays.com #atdays 18
  • 19. ЧТО ЭТО БЫЛО? – СТАТИЧЕСКИЙ PAGE OBJECT! atdays.com #atdays 19
  • 20. Позитив 01: Тест стал читабелен public static RemoteWebDriver Driver { get { return WebBrowser.Driver; } } [TestMethod] public void Donate_test_static() { MyPages.MainPage.Open(); MyPages.MainPage.GoToDonatePage(); MyPages.DonatePage.Donate_50_UAH_Using_Debit_Card(); MyPages.DonationPaymentsForm.FillDonationForm ( firstName : "Vasya", lastName : "Pupkin", securityCode : "555" ); // CUT } atdays.com #atdays 20
  • 21. Позитив 2: Удобная «точка входа» в страницы atdays.com #atdays 21
  • 22. Позитив 3: Driver стал доступен отовсюду! public static class WebBrowser { public static RemoteWebDriver _driver = null; public static RemoteWebDriver Driver { get { _driver = _driver ?? new InternetExplorerDriver(); return _driver; } } } public static RemoteWebDriver Driver { get { return WebBrowser.Driver; } } atdays.com #atdays 22
  • 23. И еще раз о позитиве Теперь жизнь браузера (драйвера) контролирует класс WebBrowser. Текущий драйвер доступен из любого участка кода Любая страница доступна из MyPages.* Наш тест теперь помещается на один экран монитора atdays.com #atdays 23
  • 24. Ограничения статического класса в C# class static class Наследоваться можно нельзя Породить много разных можно нельзя Инициализировать параметрами можно нельзя через конструктор полностью нельзя. Очень Завалить можно живучие Присвоить переменной можно нельзя Передать как параметр другому методу можно нельзя Реализовать интерфейс можно нельзя Использовать статические методы можно можно Использовать статические поля можно можно Инициализировать при помощи Webdriver нельзя "из коробки", можно PageFactory нужно написать свою фабрику atdays.com #atdays 24
  • 25. ГИБКОСТЬ – ЭТО ВАЖНО. PAGE OBJECT КАК OBJECT atdays.com #atdays 25
  • 26. Тест не изменился! Спасибо, MyPages atdays.com #atdays 26
  • 27. Изменения в MyPages public static class MyPages { public static MainPage MainPage { get { return new MainPage();} } public static DonatePage DonatePage { get { return new DonatePage(); } } } atdays.com #atdays 27
  • 28. Новая структура проекта Object Static atdays.com #atdays 28
  • 29. AbstractPageBase public abstract class AbstractPageBase { public RemoteWebDriver Driver { get { return WebBrowser.Driver; } } } atdays.com #atdays 29
  • 30. PaymentResultPage public class PaymentResultPage : AbstractPageBase { public void WaitUntilExists() { WebDriverWait wait = new WebDriverWait(Driver, TimeSpan.FromSeconds(30)); wait.Until(ExpectedConditions.TitleContains( @"Donate-error - Payments")); } public string GetResultHeaderText() { var lblFirstHeader = Driver. FindElementById(@"firstHeading"); return lblFirstHeader.Text; } } atdays.com #atdays 30
  • 31. Changelog Появился базовый класс AbstractPageBase Из MyPages.* можно по-прежнему получить любую страницу Декларация страниц была вынесена из MyPages в отдельные файлы Мы лишились ограничений статических классов ТЕПЕРЬ НАС НЕ ОСТАНОВИТЬ! atdays.com #atdays 31
  • 32. Статический/Динамический – разница в перспективах Статический atdays.com Динамический #atdays 32
  • 33. ПАТТЕРНЫ (РЕЦЕПТЫ) И ИНТЕРФЕЙСЫ (РОЛИ) atdays.com #atdays 33
  • 34. http://bash.im/quote/420885 xxx: тема письма в рабочей почте " RE: FW: FW: RE: RE: FW: RE: СРОЧНО!!!!!!" yyy: Вот это проблема структурных организаций ЦЕПОЧКА ОТВЕТСТВЕННОСТИ /CHAIN OF RESPONSIBILITY/ atdays.com #atdays 34
  • 35. Chain of Responsibility ?? ? ??? Цепочка ответственности ???? atdays.com #atdays 35
  • 36. Iinvokable public interface IInvokable { void Invoke(); bool Exists(); } Invoke – вызвать Invokable – то, что можно вызвать I invokable – Я вызываемый(-оя, -ое)! atdays.com #atdays 36
  • 37. НужнаяPage.Invoke(): НужнаяPage.Invoke(): Если я уже Exists() – то вот она я! Если я не Exists(), то я сделаю: ПредыдущаяPage.Invoke() Потом что-то нажму – вот она я! Donation Donate Payments Page Form atdays.com #atdays 37
  • 38. Что дает нам Iinvokable? Любую страницу можно вызвать с параметрами по умолчанию var page = MyPages. PaymentResultErrorInvalidCreditCard; page.Invoke(); atdays.com #atdays 38
  • 39. Что дает нам Iinvokable? Передать страницу как параметр метода public void TestThatPageExists(IInvokable page) { page.Invoke(); Assert.IsTrue(page.Exists()); } [TestMethod] public void Test_PaymentResultErrorInvalidCreditCard() { TestThatPageExists( MyPages.PaymentResultErrnvalidCreditCard ); } atdays.com #atdays 39
  • 40. Что дает нам Iinvokable? Если нужная страница уже открыта (после предыдущего теста ) – она будет использована повторно public void Invoke() { if (Exists() == false) { var mainPage = MyPages.MainPage; mainPage.Invoke(); mainPage.GoToDonatePage(); } } atdays.com #atdays 40
  • 41. I HAVE EXPECTED CONTROLS atdays.com #atdays 41
  • 42. Сышишь, а есть какиета кантролы? public interface IHaveExpectedControls : IInvokable { List<IWebElement> GetExpectedControls(); } .Invoke() .Exists() .GetExpectedControls() atdays.com #atdays 42
  • 43. Get Expected Controls (PageObject) public class DonatePage : AbstractPageBase, IHaveExpectedControls { [FindsBy(Using=@"input[name='amount'][value='50']", How = How.CssSelector)] public IWebElement rbtnDonate50; [FindsBy(Using=@"input[value='Donate by credit/debit card']", How = How.CssSelector)] public IWebElement btnMakeDonation; public List<IWebElement> GetExpectedControls() { return new List<IWebElement>() { rbtnDonate50, btnMakeDonation }; } atdays.com #atdays 43
  • 44. Позволяет писать универсальные тесты public virtual IHaveExpectedControls CurrentPage { get { return null; } } [TestMethod] public void TestExpectedControls() { CurrentPage.Invoke(); var expectedControls = CurrentPage.GetExpectedControls(); foreach (var expectedControl in expectedControls) { Assert.IsTrue(expectedControl.Displayed); } } atdays.com #atdays 44
  • 45. Авто-тесты для авто-тестов? Легкие тесты, которые: 1. Открывают каждую страницу 2. Проверяет каждый важный элемент страницы Основной тест-набор atdays.com #atdays 45
  • 46. Та да да дам! atdays.com #atdays 46
  • 47. Спасибы: За то, что доклад состоялся: Спасибо Вам! За Invoke() Виктору Линчевскому Леониду Артемьеву Помощь в подготовке доклада: Михаил Поляруш Андрей Ребров atdays.com #atdays 47
  • 48. Я не прощаюсь, я говорю: до свидания! Дима Жарий atdays.com #atdays 48