julia_v_iluhina

Untitled

Aug 27th, 2016
167
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 27.67 KB | None | 0 0
  1. /*
  2.     Ты знаешь, версия выглядит очень странной..
  3.     Странно, что у тебя она работала
  4.     Взять хотя бы не рабочие кондишены и таймаут в 4 секунды...
  5.  
  6.     Я выкачала себе твое решение
  7.     И тут буду комментировать - что я делала - чтоб у меня все работало
  8.  
  9.     что касается твоего тестового аккаунта
  10.     http://joxi.ru/n2YkKaGUjE0N6r
  11.     вот такое мне рассказывает
  12.     скорее всего - в этом причина
  13.     надо зайти вручную в этот аккаунт и все поправить
  14.     или как вариант - другой заведи
  15.  
  16.     далее - проверяю на своем тестовом аккаунте
  17.     селениум = 2.53.1
  18.     файрфокс = 46.0.1 + запрет обновляться автоматом
  19.  
  20. */
  21. ****************************************************************
  22. ****************часть 1 - assertThat & timeout *****************
  23. ****************звездочками разделяем куски слона********************
  24. ****************************************************************
  25. /*
  26.     тест падает - при попытке отправить письмо - не хватает таймаута
  27.     который = 4 секундам
  28.     нам нужно средство - которое позволит из тест-классов влиять на таймаут
  29. */
  30. -----------------------------------
  31. src / test / java / pages / Configuration.java
  32.  
  33. public class Configuration {
  34.     public static long timeout = 4;
  35. }
  36. /*
  37.     держать такой класс в src / test / java / pages
  38.     да еще и не использовать - то уже перебор))
  39.  
  40.     перемести класс в пекедж core
  41. */
  42. -----------------------------------------------
  43.    public void assertThat(ExpectedCondition<WebElement> expectedCondition, long timeoutInSceconds) {
  44. /*
  45.     перепиши этот метод вот так
  46.     public <V> V assertThat(ExpectedCondition<V> condition, long timeout)
  47.  
  48.     ты ниже - реализовала метод с сигнатурой
  49.     public <V> V assertThat(Function<? super WebDriver, V> condition)
  50.     верно реализовала - что касается работы с дженериками
  51.  
  52.     так что - возьми верные идеи в наш метод
  53.     public <V> V assertThat(ExpectedCondition<V> condition, long timeout)
  54.  
  55.     что касается типа параметра condition
  56.         да, можно применить и тип Function<? super WebDriver, V>
  57.         именно к нему приводится ExpectedCondition<V>
  58.         только вот зачем тебе себя пугать???
  59.         использовав тип ExpectedCondition<V> - получишь той же красоты реализацию
  60.     получишь вариант - см ниже
  61. */
  62.    public <V> V assertThat(ExpectedCondition<V> condition, long timeout){
  63.         return new WebDriverWait(getWebDriver(), timeout).until(condition);
  64.    }
  65. ----------------------------------------------------------
  66.     public <V> V assertThat(Function<? super WebDriver, V> condition) {
  67. /*
  68.     раз у нас уже есть красивый public <V> V assertThat(ExpectedCondition<V> condition, long timeout)
  69.     и есть Configuration.timeout - со значением таймаута
  70.  
  71.     в этом методе - вызови assertThat(ExpectedCondition<V> condition, long timeout)
  72.     и передай в качестве таймаута Configuration.timeout
  73.  
  74.     я надеюсь, тип параметра condition и тут поправила )
  75.  
  76.     получишь - метод, который выполняет ждущую проверку с таймаутом = Configuration.timeout
  77. */
  78. -----------------------------------------
  79. /*
  80.     в тест-классе - добавь BeforeClass-метод
  81.     изменяющий Configuration.timeout  = 20
  82.     в тексте задания рекомендовано 15 секунд
  83.     мне иногда не хватает
  84. */
  85. ------------------------------------------
  86. /*
  87.     запускаем-проверяем
  88.     уже не должно быть падений, вызванных маленьким таймаутом
  89.  
  90.     надо сказать - тест выполнился))
  91.     но - пока радоваться рано)))
  92. */
  93. ************************************************************************
  94. *********************** ConciseAPI - упорядочиваем ********************
  95. ***********************************************************************
  96. /*
  97.     Насколько я тебя поняла - ты решила реализовать версию, когда предок пейджа и предок тест-класса
  98.     наследуются от абстрактного класса ConciseAPI
  99.  
  100.     ок)
  101. */
  102. ---------------------------------
  103. /*
  104.     Переносим ConciseAPI в пекедж core
  105.     т к эта штука - универсальная
  106. */
  107. ----------------------------------------
  108.  
  109.     @FindBy (css = "[role=main] .zA")
  110.     private List<WebElement> mails;
  111.  
  112.     public void login(String email, String password) {
  113.     public void newMail(String to, String subject) {
  114.     public void assertMail(String text) {
  115.     public void assertMails(String... texts) {
  116.     public void switchToSent() {
  117.     public void switchToInbox() {
  118.     public void searchByText(String text) {
  119. /*
  120.     Вот это все - ранее жило в пейдже/пейджах
  121.     вот там ему и самое место
  122.  
  123.     разумно - предка делать без специфики
  124.     чистым от подробностей и универсальным
  125.     ну зачем нам в таком месте - что-то про gmail-овские инструменты
  126.  
  127.     соотвественно - в тест-методе - поправь вызовы методов
  128.  
  129.     таки внизу ревью напишу про ООП)
  130. */
  131. --------------------------------------------------
  132.  
  133. assertThatUrlIs
  134. /*
  135.     Оба метода - не используются в этом решении
  136.     да и наш универсальный assertThat - позволит и урл проверить
  137.     убиваем)
  138. */
  139. -----------------------------------------------
  140.  
  141. public static By byText(String elementText) {
  142.         return new ByText(elementText);
  143. }
  144. /*
  145.     избавляемся от лишних сложностей -
  146.     вместо использования дополнительного класса ByText
  147.     напишем код вида By.xpath(...);
  148.     и тут уже нам пригодится полезная строчка из класса ByText
  149.     используй строчку и убивай класс ByText
  150. */
  151. ----------------------------------------------------
  152.     public By byCss(String cssSelector) {
  153.     public By by(String cssSelector) {
  154. /*
  155.     прибивай метод by(String cssSelector)
  156.     byCss(String cssSelector) - уже достаточно лаконично, но все еще понятно
  157.     его достаточно
  158.  
  159.     в GmailPage ты разок использовала метод by - поправь это
  160. */
  161. ----------------------------------------------------
  162.  
  163. public abstract class ConciseAPI {
  164.  
  165.     public abstract WebDriver getWebDriver();
  166.  
  167.     public void open(String url) {
  168.  
  169.     public <V> V assertThat(ExpectedCondition<V> condition, long timeout){
  170.     public <V> V assertThat(ExpectedCondition<V> condition) {
  171.  
  172.     public WebElement $(By locator) {
  173.     public WebElement $(String cssSelector) {
  174.  
  175.     public By byCss(String cssSelector) {
  176.     public static By byText(String elementText) {
  177.     public static By byAttribute(String attributeName, String attributeValue) {
  178.     public static By byTitle(String title) {
  179. }
  180. /*
  181.     вот собственно - и все, что тут останется
  182.     только универсальное
  183.     только применимое в каком угодно селениусмском проекте
  184. */
  185. ------------------------------------------
  186. /*
  187.     проверяем-запускаем = должно работать
  188.  
  189.     радоваться по-прежнему рано)))
  190. */
  191. ********************************************************************
  192. *******************BasePage*****************************************
  193. ********************************************************************
  194. public class BasePage extends ConciseAPI{
  195. /*
  196.     к реализации - вопросов нету)
  197.     все ок реализовала
  198.  
  199.     только перенеси этот класс в core
  200.     это тоже такой класс - который может быть переиспользован в любом селениумском проекте
  201. */
  202. ********************************************************************
  203. ************************GmailPage***********************************
  204. *******************************************************************
  205. /*
  206.     вспоминай описание хорошей структуры проекта
  207.     пекедж pages - с пейджами в ветке src\main
  208.     перенеси
  209.  
  210.     внизу приведу кусочек по структуре еще раз (см конец ревью)
  211.  
  212.     вспомни селенидовскую версию этого задания
  213.     у нас было 3 пейджа )
  214.     и тут можно также реализовать, отнаследовав каждый из них от BasePage
  215. */
  216. -----------------------------------------------
  217.     public GmailPage (WebDriver driver){
  218. ...
  219.     @FindBy (css = "[role=main] .zA")
  220.     private List<WebElement> mails;
  221. /*
  222.     вот это - помести в самом начале кода пейджа
  223.  
  224.     уже говорила - проще воспринимать код, идя от общего к частному
  225.  
  226.     поравняй пропуски строк, реформатируй код
  227. */
  228. -------------------------------------
  229.     public void login(String email, String password) {
  230.  
  231.         ...
  232.         assertThat(
  233.                 presenceOfElementLocated(byCss("#Passwd")));
  234.         ...
  235. /*
  236.     ты такими проверками - затыкала проблему с нехваткой таймаута
  237.     метод $ - ждет видимости элемента в рамках таймаута
  238.  
  239.     не нужно тебе еще одно ожидание
  240.     метод $ - все нужное уже делает
  241. */
  242. -----------------------------------------------------------
  243.     public void newMail(String to, String subject) {
  244.         ...
  245.         assertThat(presenceOfElementLocated(By.name("to")));
  246.         /*
  247.             это - тоже не надо
  248.             соображения - те же
  249.         */
  250.         ...
  251.         getWebDriver().findElement(By.tagName("body")).getText().contains("Your message has been sent");
  252.         /*
  253.             эта строка возвращает true или false
  254.             и ничего не ждет))
  255.  
  256.             да и не надо тебе тут ожиданий
  257.  
  258.             убивай строку)
  259.         */
  260.     }
  261. -----------------------------------------------------------------------------------
  262.     public void assertMail(String text) {
  263.         listNthElementHasText(mails, 1, text);
  264.     }
  265.  
  266.     public void assertMails(String... texts) {
  267.         textsOf(mails, texts);
  268.     }
  269.  
  270. /*
  271.     признаться, удивила ты меня такой реализацией)
  272.  
  273.     выражения - listNthElementHasText(...) и  textsOf(...)
  274.     возвращают нам значение типа ExpectedCondition
  275.     и все)
  276.  
  277.     т е - проверок - мы не делаем
  278.  
  279.     а  - надо делать проверку
  280.     проверку мы делаем - вызывая assertThat для нужного нам кондишена
  281.  
  282.     это раз
  283.     есть еще нюансы - я их на другом примере откомментирую
  284.  
  285.     ну и до кучи - почему listNthElementHasText(mails, 1, text)
  286.     а не listNthElementHasText(mails, 0, text)
  287.  
  288.     в селенидовском проекте - с нуля нумеровали
  289.     а тут почему?
  290.  
  291.     тоже на эту тему материалов тебе накидаю - см внизу
  292. */
  293.  
  294. ---------------------------------------
  295.  
  296. /*
  297.     исправляем-запускаем = падает на проверке assertMail
  298.     с очень станной ошибкой)
  299.     org.openqa.selenium.UnhandledAlertException: Unexpected modal dialog (text: This page is asking you to confirm that you want to leave - data you have entered may not be saved.): This page is asking you to confirm that you want to leave - data you have entered may not be saved.
  300.  
  301.     ну, наверное, это хорошо - что я вижу проблему)))
  302.  
  303.     уже ближе к истине )
  304.     осталось  - привести в чувства CustomConditions
  305. */
  306. --------------------------------------------------------
  307.  
  308.  public static void refresh() {
  309.         $(".asf").click();
  310.  }
  311. /*
  312.     помнишь - был такое метод в педже - в решении селенидовском?
  313.  
  314.     почему тут от него избавилась и юзаешь  driver.navigate().refresh();?
  315.  
  316.     это ж разные вещи)
  317.  
  318.     реализуй в пейдже аналогичный метод и используй его в тест-методе
  319.  
  320.     ошибки останутся, но будут уже другими
  321.     ни про какие диалоги - речи не будет идти
  322.  
  323.     кстати - если бы отлаживала код пошагово - наверняка бы увидела эту проблему
  324.     осваивай отладку
  325. */
  326.  
  327. *************************************************************************
  328. ********************CustomConditions ****************
  329. *************************************************************************
  330.  
  331. public class CustomConditions {
  332.  
  333.     public static List actualTexts(List<WebElement> elements)
  334.     {
  335.         List<String> actualTexts;
  336.         actualTexts = new ArrayList<String>();
  337.         for (WebElement element : elements) {
  338.             actualTexts.add(element.getText());
  339.         }
  340.         return actualTexts;
  341.     }
  342.     /*
  343.         лучше имена методов формировать по принципу - что сделать=глагол + детали
  344.         https://docs.google.com/document/d/13dNyFGbI7mV22UUhH8E0LJ7SzabAmX7Bw7VCHScYfiU/edit#bookmark=id.2pvr3ijzfuho
  345.  
  346.         из списка вебэлементов - мы только actual тексты и можем выбрать)
  347.         поэтому - такие очевидные веши не указываем)
  348.         т е getTexts(List<WebElement> elements) - будет в самый раз
  349.  
  350.         дальше момент
  351.         этот метод - вспомогательный для наших кондишенов
  352.         и в общем - не завязан именно на импользование только в кондишенах
  353.         потому - его разумно вынести в класс-контейнер статических универсальных методов
  354.         (Helpers , к примеру), размести его в пекедже core
  355.         и тут - только используй
  356.  
  357.         даже если бы был у нас метод вспомогательный для кондишенов, который ну только кондишенам нужен
  358.         то его стоило разместить не в начале кода класса, а в конце - двигаться от общего к частному
  359.         так легче понимать незнакомый или забытый код)
  360.     */
  361.  ----------------------------------------------
  362.    public static ExpectedCondition<List<WebElement>> textsOf(final By elementsLocator, final String... texts) {
  363. ....
  364.             private List<String> actualTexts;
  365. /*
  366.     вот мы объявили список
  367. */
  368. ...
  369.                actualTexts(elements);
  370. /*
  371.     вот мы вызвали метод, который список возвращает
  372.     но - возвращенное значение не присвоили никакой переменной
  373.     вернули и вернули
  374.  
  375.     а List<String> actualTexts - как был не инициализированным, так и остался
  376.  
  377.     если метод тебе что-то возвращает - и тебя интересует это значение - надо
  378.     это фиксировать в некой переменной
  379.     SomeClass someVar;
  380.     ...
  381.     someVar = getValueOfSomeClass(....);
  382.     иначе - да, мы значение получили, но им не воспользовались
  383.  
  384.     тут у тебя должен быть код
  385.     не
  386.         actualTexts(elements);
  387.     а
  388.         actualTexts = actualTexts(elements);
  389.  
  390. */
  391. -------------------------------------
  392.  
  393. /*
  394.     пока прибей лишние кондишены - которые с параметром типа By  работают
  395.     сначала эти отладь
  396.     потом  - когда будешь делать версию без файндбаев - реализуешь
  397. */
  398. -------------------------------------------
  399.  
  400. public static ExpectedCondition listNthElementHasText(final List<WebElement> elements, final int index, final String text){
  401.         return new ExpectedCondition<Boolean>() {
  402.             private List<String> actualTexts;
  403.  
  404.             public Boolean apply(WebDriver driver) {
  405.  
  406.                 actualTexts = actualTexts(elements);
  407.  
  408. /*
  409.     падает на строке actualTexts = actualTexts(elements);
  410.     с ошибкой StaleElementReferenceException
  411.  
  412.     ну да, а try - ниже
  413.  
  414.     не меняй пока...
  415. */
  416. ---------------------------------------------
  417. https://docs.google.com/document/d/1BiYTLdypDfucSqiY9isv1HCKKQIxelzqYrN-3Ku1RWM/edit
  418.  
  419. /*
  420.     вот это - примени
  421.     и тогда - проблема с возникноверием исключений  будет решена аккуратнее
  422.  
  423. */
  424. -------------------------------------------------
  425.  В listNthElementHasText - странный toString()
  426. /*
  427.     в toString()  - показывай фактические тексты всех элементов и ожидаемый текст и индекс
  428.  
  429.     посмотри на формулировки в toString()  - у родных селениумских кондишенов
  430.     примени знания тут - какие-то стандартные обороты
  431.    
  432.     не надо в toString - снова получать элементы
  433.     elements.get(index)
  434.     и тут может возникнуть исключение
  435.     все, что нужно вывести - ты собрала в apply
  436.     там у нас исключения ловились, все ок было
  437. */
  438. ----------------------------------
  439. ExpectedCondition listNthElementHasText
  440. /*
  441.     реализуй этот кондишен - как ExpectedCondition<WebElement>
  442.     в случае удачной проверки - возвращай в apply элемент с таким текстом
  443.     так больше пользы будет от возвращаемого результата
  444. */
  445.  
  446. ********************Полезное - к сведению**********************************
  447. ************************************************************************
  448. **********************ООП***********************************************
  449. *************************************************************************
  450. /*
  451.     вообще не стоит злоупотреблять наследованием
  452.  
  453.     советую пересмотреть видео Composition over Inheritance
  454.     https://drive.google.com/file/d/0B8hgIBw8-V-AYkdNNDRJWVFndHc/view
  455.  
  456.     да и погугли это выражение )
  457.     мноого интересного найдешь
  458.  
  459.     если кратко и на пальцах, по наследованию
  460.     предок-потомок - хорошо и правильно реализованы
  461.     если мы можем сказать
  462.     потомок - это тоже предок
  463.  
  464.     и в этой фразе не будет ничего нелогичного
  465.  
  466.     class GmailPage extends BasePage
  467.     GmailPage = это тоже BasePage  - нормально все с логикой
  468.  
  469.     с предком тест-класса и тест-классом тоже все ОК
  470.  
  471.     а вот
  472.     class BasePage extends ConciseAPI - уже вопросы к логике
  473.  
  474.     да, мы тут с п омощью абстрактного предка технично выкрутились
  475.     с вебдрайвером и универсальными инструментами - чтоб и в пейджах, и в тесте они были доступны
  476.     но - это и правда  - недостаток текущей версии
  477.     мы ее, кстати, должны были в следующем задании реализовывать)
  478.  
  479.     не страшно, сделаем оба задания сразу
  480.  
  481.     еще момент
  482.      предок - должен содержать общее - для всех потомков
  483.      не надо в предка впихивать подробности одного из потомков
  484.      это делает логику странной и не понятной
  485.      потом - если ты забыл, или если ты такое чужого авторства видишь
  486.      очень тяжело понять - что на чем стояло
  487.  
  488.      предок - организм
  489.       он ест, дышит, живет
  490.       не пишем - что жаба например, ест вот так, живет там и т п
  491.       т к тут не только жабы будут в наследниках
  492.       тут мы схематично описываем общее в логике всех потомков
  493.  
  494.      потомок - жаба
  495.         вот тут уже даем волю уточнениям и деталям ))
  496.  
  497.      потомок - обезьяна
  498.         тут - тоже детали, но другие
  499.         и детали жабы изнутри обезьяны нам не видны
  500.         и это - хорошо и правильно
  501.  
  502.         а вот общая логика предка Организм - как раз и к обезьяне относится,
  503.         и к жабе = доступна в любом потомке
  504.         при этом - в
  505.         этой логике нет лишних, чужих деталей
  506.  
  507. */
  508. *******************************************************************
  509. *********************************************************************
  510. /*
  511. Что почитать про Generics
  512. про дженерики в общем(русский)
  513. http://www.quizful.net/post/java-generics-tutorial
  514.  
  515. http://www.tutorialspoint.com/java/java_generics.htm
  516. http://developer.alexanderklimov.ru/android/java/generic.php
  517.  
  518. конвеншенcы      http://stackoverflow.com/questions/2900881/generic-type-parameter-naming-convention-for-java-with-multiple-chars
  519. https://docs.oracle.com/javase/tutorial/java/generics/types.html
  520.  
  521. уроки
  522. http://docs.oracle.com/javase/tutorial/extra/generics/index.html
  523.  
  524. очень приличный faq (есть pdf, и есть кое-что еще, помимо дженериков)
  525. http://www.angelikalanger.com/GenericsFAQ/JavaGenericsFAQ.html
  526.  
  527. ----------------------------------------------------------
  528. для понимания кетчера (Catcher)
  529. http://grepcode.com/file/repo1.maven.org/maven2/com.google.guava/guava/r06/com/google/common/base/Function.java
  530. http://www.programcreek.com/java-api-examples/com.google.common.base.Function
  531. https://docs.oracle.com/javase/tutorial/java/generics/lowerBounded.html
  532. http://stackoverflow.com/questions/3847162/java-generics-super-keyword
  533. http://stackoverflow.com/questions/2800369/bounding-generics-with-super-keyword
  534. http://stackoverflow.com/questions/1910892/what-is-the-difference-between-super-and-extends-in-java-generics
  535.  
  536. */
  537. *******************************************************************************
  538. ********************************************************************************
  539. /*
  540. http://joxi.ru/nAyqEx7HXvxQoA
  541. http://prnt.sc/bvuytd
  542.  
  543. вот пример хорошей структуры проекта
  544.  
  545. в src \ main
  546.  
  547.   core - универсальное, что можно переиспользовать в разных проектах
  548.   pages - пейджи тоже можно переиспользовать для других тестов этого же приложения
  549.  
  550.  
  551. в src \ test
  552.  
  553.   testdata - тестовые данные (если такие есть и они вынесены в отдельный класс)
  554.   testconfigs - предки тест-класса (так можно их изолировать от  собственно тест-классов - чтоб легче было ориентироваться
  555.  
  556.  
  557. про пекеджи еще немного)
  558. если GroupID = com.somesite
  559. а проект todomvctest
  560. то пакет корневой должен быть com.somesite.todomvctest
  561.  
  562. логика  - чтобы "не смешивались имена сущностей"
  563.  
  564. внутри одной компании - может быть несколько проектов)
  565. и у всех у них один com.somesite  - базовый пекедж
  566. но для каждого проекта должен быть свой  “базовый пекедж проекта"
  567. иначе все смешается)
  568. важно то, что когда этот проект выльется в отдельную библиотеку,
  569. то не будет конфликтов при его подключении
  570. */
  571. ********************************************************
  572. /*
  573.     лучше - нумеруй с нуля и называй параметр - index
  574.  
  575.    лучше - быть понятнее для большинства
  576.    большинство в большинстве случаев столкнулось с нумерацией с нуля)
  577.    большинство увидело тот же термин -  index
  578.  
  579.  
  580.     а для индекса элемента в коллекции/массиве - применяется именно термин  index
  581.     мы используя такой термин  - лишний раз подчеркнули - нумеруем с нуля
  582.  
  583.  
  584.     надеюсь, я тебя убедила
  585.     https://en.wikipedia.org/wiki/Zero-based_numbering
  586.     http://c2.com/cgi/wiki?ZeroAndOneBasedIndexes
  587.     http://stackoverflow.com/questions/24841172/why-is-array-indexing-in-java-start-with-0
  588.  
  589. */
Advertisement
Add Comment
Please, Sign In to add comment