julia_v_iluhina

Untitled

Sep 12th, 2016
98
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 23.45 KB | None | 0 0
  1.     <dependencies>
  2.         <dependency>
  3.             <groupId>com.codeborne</groupId>
  4.             <artifactId>selenide</artifactId>
  5.             <version>3.6</version>
  6.         </dependency>
  7.         <dependency>
  8.             <groupId>junit</groupId>
  9.             <artifactId>junit</artifactId>
  10.             <version>4.12</version>
  11.         </dependency>
  12.         <dependency>
  13.             <groupId>ru.yandex.qatools.allure</groupId>
  14.             <artifactId>allure-junit-adaptor</artifactId>
  15.             <version>${allure.version}</version>
  16.         </dependency>
  17.     </dependencies>
  18. /*
  19.     pom - только селениум тебе нужен
  20.     в предыдущих заданиях - у тебя же есть примеры хорошего pom-а
  21. */
  22. ************************************************
  23. public abstract class ConciseApi {
  24.  
  25.     public abstract WebDriver getWebDriver();
  26. /*
  27.     ага, у тебя сразу получается версия следующей работы)
  28.     ок - упрощать не будем)
  29. */
  30. *************************************************
  31.     public WebElement $(WebDriver driver ,By locator){
  32.         return assertThat(driver ,ExpectedConditions.visibilityOfElementLocated((locator)));
  33.     }
  34. /*
  35.     в методе ты можешь использовать getWebDriver() и параметра WebDriver driver - уже не нужно
  36.  
  37.     собственно - идея без наследования,
  38.     но с параметром WebDriver driver во всех методах - это как раз вариант наиболее простой реализации задания
  39.  
  40.     упрощать смысла нету)
  41.  
  42.     используй import static - для ExpectedConditions.visibilityOfElementLocated
  43.     тогда в коде будет полаконичнее - visibilityOfElementLocated
  44.  
  45.     двойные скобки ((locator)) - можно упростить
  46.     достаточно (locator)
  47. */
  48. ******************************************************************
  49.     public WebElement $(WebDriver driver ,String cssSelector){
  50. /*
  51.     тут - тоже
  52.         избавься от параметра WebDriver driver
  53.         и в реализации - вызывай $(WebDriver driver ,By locator)
  54.  
  55.         это даст более DRY код
  56.         выгоды - как обычно
  57.             чуть более DRY код
  58.             чуть лаконичнее
  59.             чуть проще для понимания (понимать один код вместо двух)
  60.             чуть проще для сопровождения (менять один код вместо двух)
  61. */
  62. ***************************************************
  63.     public static int timeout =4;
  64. ...
  65.     public <T> T assertThat(WebDriver driver,ExpectedCondition<T> condition) {
  66. /*
  67.     много хороших идей
  68.      то, что вынес в переменную - таймаут
  69.      то, что в реализации метода используешь дженерик тип
  70.  
  71.     по реализации - чуть поправим
  72.         WebDriver driver - можно убрать параметр
  73.  
  74.         реализуй метод public <T> T assertThat(ExpectedCondition<T> condition, int timeout)
  75.             и второй метод - public <T> T assertThat(ExpectedCondition<T> condition)
  76.                 в котором - используй настроечную переменную timeout и первій метод
  77.  
  78.         только еще и для настроечной переменной timeout
  79.             реализуй класс Configuration
  80.             именно там будем собирать все настроечніе переменные
  81.             пока - будет только timeout
  82.  
  83.         чего мы в результате добьемся
  84.             во-первых - разделим настройки и инструменты - по разным классам
  85.             почитай про single responsibility principle
  86.  
  87.             во-вторых - у нас будет метод  assertThat(ExpectedCondition<T> condition, int timeout)
  88.             чтоб вызывать в случаях, когда надо явно задать таймаут
  89.             (например, везде ждем 4 секунды, и только какую-то одну проверку - нужен бОльший таймаут)
  90.  
  91.             в-третьих - у нас будет assertThat(ExpectedCondition<T> condition)
  92.             который будет оперировать таймаутом из настроек
  93.             что тоже удобно
  94.             раз перед тестами при необходимости - настроили таймаут
  95.             и все проверки выполняются с таким таймаутом
  96.  
  97.     и ниже - приведу полезное на почитать про джереники, вдруг что-то из этого пригодится
  98. */
  99. *****************************************************************
  100. public class BaseTest extends ConciseApi {
  101.  
  102.     public WebDriver driver;
  103.  
  104.     @Before
  105.     public void startUP(){
  106.         driver = new FirefoxDriver();
  107.     }
  108.  
  109.     @After
  110.     public void tearDown(){
  111.       driver.close();
  112.     }
  113. /*
  114.     да, можно и так)
  115.  
  116.     перед запуском каждого тест-метода - создавать вебдрайвер
  117.     и после каждого тест-метода - его удалять
  118.  
  119.     правда, не всегда это нужно
  120.     надо исходить из текущих потребностей
  121.     если все тесты отрабатывают в одном потоке - то разумнее
  122.     перед запуском всех тестов - единожды создавать вебдрайвер
  123.     и после работы всех тестов - удиножды удалять
  124.     в таком случае тебе нужна пара BeforeClass & AfterClass методов
  125.     напоминаю - они статические, и переменная driver - тоже должна быть статической в таком случае
  126.  
  127.       а что вызвать для вебдрайвера - close vs quit - почитай)
  128.         http://stackoverflow.com/questions/15067107/difference-between-webdriver-dispose-close-and-quit
  129.         http://www.testingdiaries.com/driver-close-and-driver-quit/
  130.         http://internetka.in.ua/selenium-webdriver-quit-or-close/
  131.  
  132.     про имя метода - startUP() - написание по lowerCamelCase должно быть
  133. */
  134. ***********************************************
  135. public class BasePage extends ConciseApi {
  136. /*
  137.     этот класс-предок для пейджей - универсальный
  138.     потому его можно перенести в core
  139.  
  140.  
  141.     важно - предок тест-класса - пусть и универсальный -
  142.     все авно располагаем в ветке src \ test
  143. */
  144. *************************************************************
  145.     @Step
  146.     public  void assertMail(int index, String mailText) {
  147.         Assert.assertEquals((mails.get(index).getText()), mailText);
  148.     }
  149.  
  150. /*
  151.     Assert.assertEquals - не ждущая проверка
  152.     так - проверять не надежно
  153.     лучше - реализовать кондишен listNthElementHasText(List<WebElement> elements, int index, String expectedText)
  154.     и проверять тут - с помощью ждущей проверки - с использованием этого кондишена
  155.  
  156.     суть проверки
  157.     получаем такой-то элемент списка
  158.     у него - его текст
  159.     если текст содержит expectedText - значит проверка прошла
  160.     если нет - значит - не прошла
  161. */
  162. ************************************
  163. ...
  164. //mails.assertMailTexts(subject);
  165. /*
  166.     и для реализации этой проверки нужен кондишен
  167.  
  168.     аналог texts в селениде
  169.  
  170.     тут у тебя будет textsOf(List<WebElement> elements,String... expectedTexts)
  171.     схема проверки та же
  172.         получили тексты всех элементов списка
  173.         сравнили размер списка с фактическими текстами с коичеством переданных текстов
  174.         если не равны - проверка не прошла
  175.         если равны - сравниваем тексты попарно - нулевой - с нулевым, первый - с первым и т д
  176.         если фактический текст содержит ожидаемый - проверяем дальше
  177.         иначе - при первом не сопадении - проверка не прошла
  178.         а если проверили все пары и все ок - проверка прошла
  179.  
  180.     т е - проверили - количество, порядок и сами тексты
  181.  
  182.     а в toString кондишена
  183.          выводи - что проверял + для чего проверял
  184.          что ждали
  185.          и что получили
  186.          и вот тут тебе и пригодится собранные в список фактические тексты элементов списка
  187.  
  188.     подсказки по логике - можно подсмотреть в кондишене texts - селенидовском
  189.     подсказки по селениумским кондишенам - можно подсмотреть в классе ExpectedConditions
  190.     (напиши в коде + зажми ctrl + кликни = откроется исходній код)
  191.  
  192.     есть еще моменты
  193.     в процессе выполнения кода в apply - могут возникать исключения
  194.     это надо обрабатывать
  195.     попробуй переварить вот это
  196.     https://docs.google.com/document/d/1BiYTLdypDfucSqiY9isv1HCKKQIxelzqYrN-3Ku1RWM/edit?usp=sharing
  197.     в качестве параметра этого кетчера - можно применять ExpectedCondition<V> condition
  198.     ниже - будут пояснения - почему
  199.     если про кетчера  - пока не понятно - постарайся осознать - что ряд исключений надо ловить в apply кондишена
  200.     и это применить
  201.  
  202.  
  203.     вообще - работы пошли уже не простые)
  204.     приходи в слек, я ежедневно есть - после 21-00
  205.     и во второй половине дня в будние дни
  206.     многое в режиме вопросов-ответов - разберем
  207.  
  208.     здесь и далее - это уже будет нормой)
  209. */
  210. ***********************************
  211.     @Step
  212.     public  void goToInbox(){
  213.         $(getWebDriver(), byText("Входящие")).click();
  214.     }
  215. /*
  216.     тут тоже интересно)
  217.  
  218.     если искать по тексту - как правило - происходит клик не на линке - папка Входящие
  219.     а на первом письме из списка отправленных (потому что  есть такой текст в описании письма)
  220.  
  221.     тебе нужна реализация byTitle(...)
  222.     это можно в селениде подсмотреть
  223.  
  224.     и еще
  225.     если во входящих есть не прочитанные - byTitle(...), организованный как в селениде - не сработает
  226.     т к поиск текста - не по вхождению, а по равенству
  227.     надо бы адаптировать)
  228.  
  229.     в faq - есть полезные таблички по xPath-у
  230.     https://docs.google.com/document/d/13dNyFGbI7mV22UUhH8E0LJ7SzabAmX7Bw7VCHScYfiU/edit#bookmark=id.lirnyzxrth5n
  231.     советую скачать и пользоваться)
  232.  
  233. */
  234. ******************************************************************
  235. *********************************************************************
  236. ***********************************************************************
  237. /*
  238.     это на почитать
  239.     возможно - ты и так это уже разобрал
  240.     привожу на всякий случай
  241. */
  242.  
  243. /*
  244.      Кодишенов есть много и разных
  245.         и далеко не все они ExpectedCondition<Boolean>
  246.         вот в этих <...> - могут быть разные типы
  247.         если совсем грубо - то результат вот этого ... типа и вернет нам WebDriverWait(...).until(...) -
  248.  
  249.         например
  250.              есть такой кондишен ExpectedCondition<WebElement> visibilityOfElementLocated(By locator)
  251.              https://seleniumhq.github.io/selenium/docs/api/java/org/openqa/selenium/support/ui/ExpectedConditions.html#visibilityOfElementLocated-org.openqa.selenium.By-
  252.  
  253.              это значит WebDriverWait(...).until(visibilityOfElementLocated(...)) - вернет вебэлемент, видимость которого мы ждали
  254.  
  255.              а для кондишенов ExpectedCondition<Boolean> - new WebDriverWait(...).until вернет результат типа Boolean
  256.  
  257.              это не отменяет главной схемы работы - если проверка new WebDriverWait(...).until( - не проходит за таймаут -
  258.              то вызывается исключение
  259.  
  260.              но - помимо этого - есть вот такая разница ...
  261.  
  262.         пока наш assertThat возвращает void  - нас это может не сильно тревожить )
  263.         достаточно - в описании параметров убрать уточнение типа - не ExpectedCondition<Boolean>, а ExpectedCondition
  264.         и assertThat - будет работать с любым из кондишенов
  265.         правда - ничего нам не вернет)
  266.  
  267.         а вот если хочется получить результат new WebDriverWait(...).until( -
  268.         да еще и не городить кучу методов - придется подумать и немного теории почитать
  269. */
  270. /*
  271.     Давай разберемся. Сначала "идейно".
  272.  
  273.     Этот метод until возвращает такую интересную динамическую штуку-аватар...
  274.     "воплощение" которого зависит от того что именно ты передашь вейт антилу параметром
  275.     - точнее - какой именно кондишен ты ему передаешь...
  276.  
  277.     А кондишены бывают "разные"... "Разность" эта определеятся "параметром типа" который в джава записывается
  278.     ИмяТипа<ЗДЕСЬ>
  279.  
  280.     Ты уже ведь использовал списки, например...
  281.     В частности - List<WebElement>
  282.  
  283.     вот в такой записи типа - его параметром, выступает WebElement, указывая джаве,
  284.     что это не просто список, а "список ВебЕлементов"
  285.     а мог бы быть и списком стрингов например - List<String> или еще чего :)
  286.  
  287.     Такие "умные" типы которые получают параметр (или несколько параметров) - так и называются - параметризированными
  288.     (а фича языка, в которой они поддерживаются называется - параметрическим полиформизмом -
  289.     не путать с тем другим полиморфмизом... который называется - subtyping polymorphism,
  290.     а в джава все его знают как просто "полиморфизм")...
  291.     Еще они называются - шаблоны... или дженерики...
  292.     Именно так - Java Generics - их принято называть в Java
  293.  
  294.     Так вот... таким же дженериком является тип ExpectedCondition
  295.     который может быть параметризирован...
  296.  
  297.     Ты уже встречал запись типа:
  298.     ExpectedCondition<Boolean>
  299.  
  300.     что же значит этот булеан? что он параметризирует?
  301.     А он параметризирует внутреннюю реализацию этого кондишена...
  302.     Он определяет то, каким должен быть тип возвращаемого значения в методе apply
  303.  
  304.     То есть...
  305.     Если ты поставишь цель создать кондишен ExpectedCondition<Boolean> - ты должен будешь реализовать
  306.     его метод apply -  как возвращающий тип Boolean
  307.  
  308.     Но зачем вообще нам париться о типе возвращаемой сущности метода apply?
  309.  
  310.     А потому, что есть еще один "умный дженерик"...
  311.     Только который не "параметризированный класс", а "параметризированный метод"
  312.     (в джава бывают как Generic Types так и Generic Methods)
  313.  
  314.     и этот параметризированный метод - как раз и есть наш wait.until
  315.  
  316.     особенность реализации этого метода в том... что он вызывает внутри метод apply
  317.     нашего кондишена... и запоминает то значение, которое этот метод apply возвращает...
  318.  
  319.     И потом... в конце всей истории... этот метод until - либо бросит исключение
  320.     (в случае если "не дождется" кондишена)
  321.     либо вернет то, что вернул метод apply в "случае успеха"...
  322.  
  323.     Получается... Если ты передашь вейт антилу кондишен параметризированный типом Boolean
  324.     то в случае успеха антил - вернет тру...
  325.  
  326.     то есть ты можешь писать код вида:
  327.  
  328.     if (wait.until(enabled(composeButton))) {
  329.        doSomething();
  330.     }
  331.  
  332.     но на самом деле, такое нужно не часто...
  333.     то есть - такие кондишены - которые
  334.     параметризированы типом булеан...
  335.  
  336.     бошьше толку как раз от кондишенов параметризированных типом "того, характеристики чего ждет кондишен"...
  337.  
  338.     вот кондишен visibilityOf - как раз параметризирован типом WebElement
  339.         ExpectedCondition<WebElement>
  340.  
  341.     и его метод apply возвращает обьект типа WebElement,
  342.     а "идейно" - возвращает этот же элемент, визибилити которого мы дожидались...
  343.     (если бы мы не дождались - apply вернул бы null - что в этом случае играет роль "false")
  344.  
  345.     а until в конце концов вернет то, что вернет apply
  346.     и именно поэтому мы можем писать такой код:
  347.  
  348.         wait.until(visibilityOf(composeButton)).click()
  349.  
  350.     теперь твоим заданием будет - переделать assertThat что бы он возвращал то что возвращает wait.until
  351.  
  352.     ну и потом - переделать все свои кондишены, что бы они были параметризированы типом той сущности,
  353.     характеристики которой они должни дожидаться (кстати так выражатся немного некорректно - ведь кондишен не ждет,
  354.     он только выдает информацию - да/нет - а ждет уже вейт антил, ну то такое:) )
  355.  
  356.     для того, чтобы "правильно реализовать этот wait.until" -
  357.     тебе придется разобраться с этими дженериками...
  358.     И с дженерик типами и дженерик методами.
  359.  
  360.     И даже этого будет мало...
  361.     Придется покопаться в коде селениума, чтобы понять, что там за тип реально получает
  362.     вейт антил как кондишен...
  363.     Потому что он получает не ExpectedCondition а что то еще более странное...
  364.     Это работает - потому что это "странное" - есть родительским классом для ExpectedCondition
  365. */
  366.  
  367. /*
  368.     Что почитать про Generics
  369.     про дженерики в общем(русский)
  370.     http://www.quizful.net/post/java-generics-tutorial
  371.  
  372.     http://www.tutorialspoint.com/java/java_generics.htm
  373.     http://developer.alexanderklimov.ru/android/java/generic.php
  374.  
  375.     конвеншенcы      http://stackoverflow.com/questions/2900881/generic-type-parameter-naming-convention-for-java-with-multiple-chars
  376.     https://docs.oracle.com/javase/tutorial/java/generics/types.html
  377.  
  378.     уроки
  379.     http://docs.oracle.com/javase/tutorial/extra/generics/index.html
  380.  
  381.     очень приличный faq (есть pdf, и есть кое-что еще, помимо дженериков)
  382.     http://www.angelikalanger.com/GenericsFAQ/JavaGenericsFAQ.html
  383.  
  384.     ----------------------------------------------------------
  385.     для понимания кетчера (Catcher)
  386.     http://grepcode.com/file/repo1.maven.org/maven2/com.google.guava/guava/r06/com/google/common/base/Function.java
  387.     http://www.programcreek.com/java-api-examples/com.google.common.base.Function
  388.     https://docs.oracle.com/javase/tutorial/java/generics/lowerBounded.html
  389.     http://stackoverflow.com/questions/3847162/java-generics-super-keyword
  390.     http://stackoverflow.com/questions/2800369/bounding-generics-with-super-keyword
  391.     http://stackoverflow.com/questions/1910892/what-is-the-difference-between-super-and-extends-in-java-generics
  392.  
  393.     если осилишь после этого и применение кетчера(то, что в прошлом ревью отложили) - можно уже сейчас
  394.     по-прежнему - кетчера можно отложить
  395. */
Advertisement
Add Comment
Please, Sign In to add comment