За пределами PageObject

2,142 views
1,950 views

Published on

За пределами PageObject, Дмитрий Жарий
Есть ли необходимость в использовании объектно-ориентированного подхода в автоматизации тестирования? Нужно ли нам экономить исходный код, или лучше скопировать, вставить и подправить? Что лучше, “сложное” ООП или простые “дубовые” тесты. Ответ зависит от Вашего проекта автоматизации и от дальнейших планов его развития. Если Вы планируете остановится на десятке тестов, то в таком случае в “более сложных практиках” необходимости нет. Если же Вы планируете долгосрочное развитие фреймворка автоматизации, то задуматься о правильной архитекторе и будущем росте необходимо уже прямо сейчас.

В своем докладе Дмитрий расскажет, как очень несложные практики ООП помогут сделать код еще проще и понятней. И поверьте, в хорошем коде может разобраться любой человек, а горы “вечно падающего копи-паста” будут просто ненавидеть. Также Дмитрий расскажет о том, как Автоматизация может тестировать сама себя при помощи легких UI тестов перед тем, как запустить более тяжелые функциональные тесты и сценарии. Он покажет, как написав код тестового набора всего лишь один раз, применить его для каждой страницы отдельно. Примеры кода к докладу будут на C#/.NET. Но, любую такую практику можно реализовать на любом общеизвестном и популярном языке программирования.

Published in: Technology
2 Comments
3 Likes
Statistics
Notes
No Downloads
Views
Total views
2,142
On SlideShare
0
From Embeds
0
Number of Embeds
787
Actions
Shares
0
Downloads
16
Comments
2
Likes
3
Embeds 0
No embeds

No notes for slide

За пределами PageObject

  1. 1. За пределами PageObject Дмитрий Жарийatdays.com
  2. 2. Давайте познакомимся!Дима Жарийatdays.com #atdays 2
  3. 3. Аджендиум… [OK]=================================================1. Вам не нужен PageObject2. Вам нужен PageObject3. PageObject – это паттерн, шаблон… ИДЕЯ!4. Статический PageObject5. Динамический PageObject6. За пределами: • Паттерн «Цепочка ответственности» и .Invoke() • Интерфейс IHaveExpectedControls • Наследование в тестахatdays.com #atdays 3
  4. 4. ВАМ ДЕЙСТВИТЕЛЬНО НУЖЕН PAGE OBJECT?atdays.com #atdays 4
  5. 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. 6. Нет. Если у вас несколько сложных тестовatdays.com #atdays 6
  7. 7. Ведь код можно улучшитьatdays.com #atdays 7
  8. 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. 9. И, если у вас все под контролем…atdays.com #atdays 9
  10. 10. ВАМ НЕ НУЖЕН PAGE OBJECT!atdays.com #atdays 10
  11. 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. 12. Когда приходит Хаос… "Тест-простыней" становится слишком много В коде не разобраться без пол-литру На поддержку уходит уж слишком много времени Легче всё переписать заново Начинаете ненавидеть разработчиков, которые вынесли div из spanatdays.com #atdays 12
  13. 13. PageObject – он как книжная полка Pages LoginPage → Login(name, passwd) MainPage → LogOut() → GotoProjects() → GotoUserProfile() → Search(text)atdays.com #atdays 13
  14. 14. PAGE OBJECT – ОН ГИБКИЙatdays.com #atdays 14
  15. 15. PageObject – это: Концентрация на языке задачи,а не на языке решенияatdays.com #atdays 15
  16. 16. PageObject – главная цель Обеспечить хранение локаторов в отдельном классе Обеспечить повторное использование локаторов и/или действий над страницей без дублирования кода Обеспечить слой абстракции от «драйвера» так, чтобы в тестах не использовались физические элементы идентификации элементов управления приложениемatdays.com #atdays 16
  17. 17. А выглядит всё вот так MainPage Т Е С Create Т Account Pageatdays.com #atdays 17
  18. 18. Демо!atdays.com #atdays 18
  19. 19. ЧТО ЭТО БЫЛО? – СТАТИЧЕСКИЙ PAGE OBJECT!atdays.com #atdays 19
  20. 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. 21. Позитив 2: Удобная «точка входа» в страницыatdays.com #atdays 21
  22. 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. 23. И еще раз о позитиве Теперь жизнь браузера (драйвера) контролирует класс WebBrowser. Текущий драйвер доступен из любого участка кода Любая страница доступна из MyPages.* Наш тест теперь помещается на один экран монитораatdays.com #atdays 23
  24. 24. Ограничения статического класса в C# class static class Наследоваться можно нельзя Породить много разных можно нельзя Инициализировать параметрами можно нельзя через конструктор полностью нельзя. Очень Завалить можно живучие Присвоить переменной можно нельзя Передать как параметр другому методу можно нельзя Реализовать интерфейс можно нельзя Использовать статические методы можно можно Использовать статические поля можно можно Инициализировать при помощи Webdriver нельзя "из коробки", можно PageFactory нужно написать свою фабрикуatdays.com #atdays 24
  25. 25. ГИБКОСТЬ – ЭТО ВАЖНО. PAGE OBJECT КАК OBJECTatdays.com #atdays 25
  26. 26. Тест не изменился! Спасибо, MyPagesatdays.com #atdays 26
  27. 27. Изменения в MyPagespublic static class MyPages{ public static MainPage MainPage { get { return new MainPage();} } public static DonatePage DonatePage { get { return new DonatePage(); } }}atdays.com #atdays 27
  28. 28. Новая структура проекта Object Staticatdays.com #atdays 28
  29. 29. AbstractPageBasepublic abstract class AbstractPageBase{ public RemoteWebDriver Driver { get { return WebBrowser.Driver; } }}atdays.com #atdays 29
  30. 30. PaymentResultPagepublic 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. 31. Changelog Появился базовый класс AbstractPageBase Из MyPages.* можно по-прежнему получить любую страницу Декларация страниц была вынесена из MyPages в отдельные файлы Мы лишились ограничений статических классов ТЕПЕРЬ НАС НЕ ОСТАНОВИТЬ!atdays.com #atdays 31
  32. 32. Статический/Динамический – разница в перспективах Статическийatdays.com Динамический #atdays 32
  33. 33. ПАТТЕРНЫ (РЕЦЕПТЫ) И ИНТЕРФЕЙСЫ (РОЛИ)atdays.com #atdays 33
  34. 34. http://bash.im/quote/420885xxx: тема письма в рабочей почте " RE: FW: FW: RE: RE: FW: RE: СРОЧНО!!!!!!"yyy: Вот это проблема структурных организаций ЦЕПОЧКА ОТВЕТСТВЕННОСТИ /CHAIN OF RESPONSIBILITY/ atdays.com #atdays 34
  35. 35. Chain of Responsibility ?? ? ??? Цепочка ответственности ????atdays.com #atdays 35
  36. 36. Iinvokablepublic interface IInvokable{ void Invoke(); bool Exists();} Invoke – вызвать Invokable – то, что можно вызвать I invokable – Я вызываемый(-оя, -ое)!atdays.com #atdays 36
  37. 37. НужнаяPage.Invoke():НужнаяPage.Invoke():Если я уже Exists() – то вот она я!Если я не Exists(), то я сделаю: ПредыдущаяPage.Invoke() Потом что-то нажму – вот она я! Donation Donate Payments Page Formatdays.com #atdays 37
  38. 38. Что дает нам Iinvokable? Любую страницу можно вызвать с параметрами по умолчанию var page = MyPages. PaymentResultErrorInvalidCreditCard; page.Invoke();atdays.com #atdays 38
  39. 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. 40. Что дает нам Iinvokable? Если нужная страница уже открыта (после предыдущего теста ) – она будет использована повторно public void Invoke() { if (Exists() == false) { var mainPage = MyPages.MainPage; mainPage.Invoke(); mainPage.GoToDonatePage(); } }atdays.com #atdays 40
  41. 41. I HAVE EXPECTED CONTROLSatdays.com #atdays 41
  42. 42. Сышишь, а есть какиета кантролы? public interface IHaveExpectedControls : IInvokable { List<IWebElement> GetExpectedControls(); } .Invoke() .Exists() .GetExpectedControls()atdays.com #atdays 42
  43. 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. 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. 45. Авто-тесты для авто-тестов? Легкие тесты, которые: 1. Открывают каждую страницу 2. Проверяет каждый важный элемент страницы Основной тест-наборatdays.com #atdays 45
  46. 46. Та да да дам!atdays.com #atdays 46
  47. 47. Спасибы: За то, что доклад состоялся: Спасибо Вам! За Invoke() Виктору Линчевскому Леониду Артемьеву Помощь в подготовке доклада: Михаил Поляруш Андрей Ребровatdays.com #atdays 47
  48. 48. Я не прощаюсь, я говорю: до свидания!Дима Жарийatdays.com #atdays 48

×