julia_v_iluhina

Untitled

Oct 15th, 2016
99
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 22.83 KB | None | 0 0
  1. public abstract class ConciseAPI {
  2. /*
  3.     не с самого примитивного варианта ты начала)
  4.  
  5.     конечно, упрощать не будем, просто  - сделаем эту и следующую работу - как одну
  6.  
  7.     сейчас объясню про самый простой вариант
  8.     мы его делать не будем, но эти объяснения нам понадобятся для последующих заданий
  9.  
  10.     можно было реализовать проще - все методы ConciseAPI
  11.     в которых требовуется вебдрайвер - снабдить еще одним параметром для вебдрайвера
  12.     и не применять наследование от ConciseAPI
  13.     да, вызовы этих методов получатся немного громоздкими - плата за простоту реализации
  14.     напоминаю - мы не будем упрощать до этой версии)
  15. */
  16. *****************************
  17.  
  18.     public void open(){
  19.         getWebDriver().get("https://mail.google.com");
  20.     }
  21. /*
  22.     тут, в ConciseAPI - разумнее реализовывать методы универсально
  23.     без привязки к особенностям реализуемых тестов
  24.  
  25.     потому - разумнее реализовать метод open(String url)
  26. */
  27. ***********************************************
  28.     public WebElement $(By locator){
  29.     public WebElement $(String cssSelector){
  30. /*
  31.     с реализацией этих методов - согласна полностью
  32.     надеюсь, тебе понятно, почему в данном случае assertThat возвращает WebElement )
  33.     на всякий случай - приведу пояснения этого момента
  34.     (уже в конце ревью такие пространные пояснения приведу)
  35. */
  36. *********************************************
  37.     public List<WebElement> $$(By locator){
  38.         return assertThat(visibilityOfAllElementsLocatedBy(locator));
  39.     }
  40.  
  41.     public List<WebElement> $$(String cssSelector){
  42.         return $$(By.cssSelector(cssSelector));
  43.     }
  44. /*
  45.     а с методом $$ - не так все просто)
  46.     если для реализации $ - нам и правда достаточно было ждать видимости элемента
  47.     т к чтоб работать с элементом - он нам в 99% нужен видимым
  48.  
  49.     то со списком - не все так просто)
  50.     кстати, полюбопытствуй - как реализован кондишен visibilityOfAllElementsLocatedBy
  51.     зажми ctrl + кликни на имени єтого кондишена
  52.     ты удивишься )
  53.  
  54.     часто списки элементов загружаются постепенно
  55.     и нам в разных случаях - нужно ждать разного
  56.     вспомни предыдущую работу - как перед followLink мы ждали minimumSizeOf
  57.  
  58.     да и пока - нам вообще не нужен метод $$
  59.     ниже поясню - почему
  60. */
  61. ****************************************************
  62.     public <V> V assertThat(Function<? super WebDriver, V> condition){
  63.         return (new WebDriverWait(getWebDriver(), 10)).until(condition);
  64.     }
  65. /*
  66.     реализовала метод - грамотно )
  67.  
  68.     действительно, у ExpectedCondition<V> - вот такой предок Function<? super WebDriver, V>
  69.     и именно объект такого типа Function<? super WebDriver, V> - и ждет метод until
  70.  
  71.     т к это класс предка для ExpectedCondition<V> - мы в метод until можем передавать значения типа
  72.     ExpectedCondition<...>
  73.  
  74.     поскольку в метод assertThat в качестве параметра ты будешь передавать только значения типа
  75.     ExpectedCondition<...> - то и у этого метода можно объявить параметр типа ExpectedCondition<V>
  76.  
  77.     станет чуть понятнее и лаконичнее
  78.  
  79.     в принципе - это не обязательно делать)
  80.  
  81.     тут - уже почти ок)
  82.  
  83.         надо добавить немного гибкости
  84.  
  85.         ведь не всегда таймаут именно такого размера требуется
  86.  
  87.         если
  88.         реализовать assertThat со вторым параметром - таймаутом
  89.         то
  90.         можно будет при вызове проверки  - явно указывать размер таймаута
  91.         это бывает удобно - когда в проекте есть проверки, требующие какого-то не стандартного таймаута
  92.  
  93.         в то же время
  94.         для всех проверок указывать таймаут - уже перебор)
  95.         потому - реализуем второй assertThat - уже без параметра - таймута
  96.         в нем - вызовем первый assertThat и в качестве таймаута укажем значение Configuration.timeout
  97.         Тут же, в core, реализуем класс Configuration со статическим полем timeout,
  98.         в котором будет задан таймаут по умолчанию (разумно его установить равным 4 секунды)
  99.  
  100.         А если для тестов значения по умолчанию Configuration.timeout недостаточно
  101.         то всегда есть возможность в  тест-классе настроить самостоятельно Configuration.timeout
  102.  
  103.         Собственно - мы аналогично поступали - когда реализовывали версию этого задания на Selenide
  104.         мы для этого теста изменяли значение Configuration.timeout
  105. */
  106. *********************************
  107. public class Main extends ConciseAPI{
  108. /*
  109.     реализация для предка пейджа - верная
  110.     единственное - теперь, в этой работе
  111.     мы уже не сможем использовать пейджи в качестве пейджей-модулей
  112.  
  113.     а будем создавать пейджи-объекты
  114.     вспомни работы по пейджам
  115.     для пейджей объектов - имя класса должно заканчиваться на Page
  116.  
  117.     все классы пейджей и их предка - переименуй
  118.  
  119.     а для предка - вообще стоит применить имя BasePage
  120.     и перенести его в core - т к его реализация универсальна
  121.     и может быть применена и для других проектов
  122. */
  123. ****************************************
  124.  public void assertNthMail(int index, String mailText){
  125.         assertThat(textToBePresentInElement($$(mails).get(index), mailText));
  126.  }
  127. /*
  128.     Вот тут - очень важный момент
  129.     его надо понять и запомнить обязательно
  130.  
  131.     если у кондишена первый параметр - WebElement или List<WemElement> -
  132.     то кондишен ждет не просто элемент или список элементов
  133.     кондишен ждет лейзи прокси элемент или список элементов (аннотированный @FindBy)
  134.     потому что - такие элементы - могут переискиваться
  135.  
  136.     а если у кондишена первый параметр - By - локатор для элемента или списка элементов
  137.     то уже внутри кондишена по локатору происходит получение элемента или списка элементов
  138.     и мы в таком случае не нуждаемся в лейзи прокси элементах или списках элементов (аннотированных @FindBy)
  139.  
  140.     еще момент
  141.     предположим, у тебя есть лейзи прокси List<WebElement> elements;
  142.     вот такой элемент elements.get(...) - не будет лейзи прокси
  143.     это - уже обычный вебэлемент
  144.     его передавать в кондишен бесполезно
  145.  
  146.     в этой работе - можно реализовать задание как с использовалием лейзи прокси списка элементов - для списка мейлов
  147.     так и используя локатор для списка мейлов
  148.     это на твое усмотрение
  149.  
  150.     в любом случае - не удастся работать с textToBePresentInElement
  151.     т к в этот кондишен - надо передать лейзи прокси элемент
  152.     которого у нас нету)
  153.  
  154.     почитать про лейзи прокси
  155.         http://selenium2advanced.blogspot.com/2013/08/working-with-page-factory-and-webdriver.html
  156.     понятная внятная
  157.         https://github.com/SeleniumHQ/selenium/wiki/PageFactory
  158.         http://joxi.ru/KAxzGoyu4NGlNm
  159. */
  160. /*
  161.     тут тебе нужен новый кондишен)
  162.     listNthElementHasText(final ... elements, final int index, final String expectedText)
  163.     который для проверит текст нн-ого элемента
  164.  
  165.     уже мы писали кондишены, правда попроще
  166.     теперь - усложним задачку
  167.  
  168.     но сначала давай обговорим тип первого параметра
  169.     мы можем написать кондишен для List<WebElement> elements
  170.     или для By elements
  171.  
  172.     если выбираешь первый вариант - пишем кондишен для лейзи прокси списка (полученного через FindBy)
  173.     написать и тот, и тот кондишен - примерно одинаково усилий нужно
  174.  
  175.     решай сама - какой вариант реализовать
  176. */
  177. ****************************
  178.     public void assertMails(String... mailTexts){
  179.         List<WebElement> webElementList = $$(mails);
  180.         String[] mailTextArr = mailTexts.clone();
  181.         int i = 0;
  182.         for (WebElement webElement : webElementList) {
  183.             assertThat(textToBePresentInElement(webElement, mailTextArr[i]));
  184.             i++;
  185.         }
  186.     }
  187. /*
  188.     Писала тебе выше - про то, что ждущая проверка visibilityOfAllElementsLocatedBy для списка - мало что дает)
  189.  
  190.     вот, мы получили список вебэлементов (не лейзи прокси = даже если на странице далее будут изменения -
  191.     они никак не повлияют на стотояние нами полученного списка)
  192.  
  193.     это первая проблемка
  194.     и вторая - что мы в textToBePresentInElement - также передаем вебэлемент, который уже не будет переискиваться
  195.     а это не имеет смысла
  196.  
  197.     нам и тут понадобится новый кондишен
  198.     аналогичный по логике селенидовскому texts
  199.  
  200.     что касается работы с varArgs - параметром метода - String... mailTexts
  201.     можно обойтись и без массива mailTextArr
  202.     почитай http://www.linkex.ru/java/varargs.php
  203. */
  204. /*
  205.     Итак, нам нужен кондишен для коллекции элементов - texts
  206.  
  207.     в селениуме - такого кондишена нету
  208.     и мы его напишем и разместим в CustomConditions
  209.  
  210.     можно заглянуть в реализацию селенидовского кондишена - чтобы использовать
  211.     идеи из логики проверки
  212.  
  213.     давай сначала разберемся с типом кондишена, который будем реализовывать
  214.     можно реализовать ExpectedCondition<Boolean>
  215.     тогда в случае успеха - assertThat - вернет True
  216.     в случае не успеха - тест упадет (как ему и положено)
  217.     а метод apply кондишена - будет возвращать
  218.     True - если проверка пройдена
  219.     False - если она не пройдена
  220.  
  221.     мы можем больше пользы извлечь из ситуации, если такой кондишен будет типа
  222.     ExpectedCondition<List<WebElement>>
  223.     тогда в случае успеха - assertThat вернет List<WebElement>
  224.     и можно будет писать что-то такое - assertThat(sizeOf(elementsList,10)).get(9).click();
  225.     (это если кондишен sizeOf был бы реализован с первым параметром - List<WebElement>)
  226.     а метод apply кондишена - будет возвращать
  227.         List<WebElement> - если проверка пройдена
  228.             в случае работы с лейзи прокси списком элементов - тот же лейзи прокси список,
  229.             который получили на входе
  230.              в случае работы с локатором  - список вебэлементов на момент, когда проверка пройдена
  231.         null - если она не пройдена
  232.  
  233.     так
  234.     с типом кондишена определились
  235.     нужен кондишен ExpectedCondition<List<WebElement>>
  236.  
  237.     теперь с параметрами
  238.     проверяем  - лейзи прокси список веб элементов - List<WebElement> elements
  239.     что проверяем у этого списка - текстЫ = String... expectedTexts
  240.  
  241.     Загляни в  селениумский класс ExpectedConditions
  242.     (в коде - зажав ctrl + кликнув на имя любого стандартного селениумского кондишена)
  243.     там можно почерпнуть ряд идей
  244.  
  245.     нам - в apply кондишена - надо принять решение - в ЭТОМ состоянии - список удовлетворяет условию или нет
  246.     а ЭТО состояние - предполагает - что  оно на протяжении анализа - не меняется)
  247.  
  248.     т е задача номер один = зафиксировать = ЭТО состояние (это актуально для варианта с лейзи прокси списом)
  249.  
  250.     и задача номер два = если проверка не прошла - в toString()  кондишена описать ожидаемые и фактические тексты
  251.     а их надо готовить еще в apply - чтобы в toString() - просто вывести
  252.  
  253.     получается - что независимо от того, будем ли мы реализовывать кондишен для лейзи прокси списка элементов или
  254.     для локатора списка элементов - нам в apply нужно получить список текстов элементов
  255.  
  256.     используй список строк для того, чтобы сохранить в нем тексты всех элементов ашего лейзи-прокси списка
  257.  
  258.     получили список актуальных текстов
  259.  
  260.     теперь - работаем только с ним - (это и есть ЭТО состояние для лейзи прокси списка)
  261.     сравни размер списка актуальных текстов и количество переданных ожидаемых текстов
  262.     если количество не равное - уже проверка не прошла
  263.  
  264.     если количество равное - сравнивай тексты
  265.         нулевого актуального текста - с нулевым ожидаемым,
  266.         первого - с первым и т д
  267.         если какой-либо актуальный текст не содержит ожидаемого текста - проверка не прошла
  268.         если тексты всех элементов прошли проверку - вот только в этом случае проверка прошла
  269.  
  270.      реализуем метод toString у кондишена
  271.          когда проверка не проходит - эта информация выводится в описании ошибки
  272.          потому - тут мы должны описать - и актуальное (ЭТО состоняние - которое мы зафиксировали в списке строк)
  273.          и ожидаемое состояние (переданные в кондишен ожидаемые тексты)
  274.  
  275.     тестируй написанный кондишен - используя
  276.          проверку, которая должна пройти (она должна пройти)
  277.          проверку, которая не должна пройти (она не должна пройти + сообщение об ошибке должно быть понятным)
  278.          так надо поступать с любым кондишеном, который самостоятельно реализуешь
  279.  
  280. */
  281.  
  282. /*
  283.        Итого)
  284.        Нам нужны 2 новых кондишена
  285.  
  286.            первый кондишен - textsOf(... elements, String... texts)
  287.             где параметры - список элементов (или его локатор) и текстЫ которые мы будем проверять для каждого из элементов
  288.  
  289.            второй кондишен - listNthElementHasText(.... elements, int index,  String text)
  290.             где параметры - список элементов(или его локатор), индекс проверяемого элемента
  291.                и текст который мы для него проверим
  292.  
  293.        Про textsOf - выше подробно обсудили
  294.        думаю, большинство вопросов про listNthElementHasText ушли автоматом)
  295.  
  296.        Но если вдруг остались
  297.  
  298.        стандартные кондишены реализованы в классе ExpectedConditions
  299.        напиши ExpectedConditions в своем коде
  300.        зажми ctrl+кликни на ExpectedConditions
  301.        откроется модуль (ниже этого комментария привела код этих 2-ух кондишенов,
  302.        в принципе, ты и сама в IntelIJ Idea сможешь это увидеть, но и тут привожу их)
  303.  
  304.        Еще источники полезных сведений
  305.            У тебя есть лекция Якова, которая рассказывает, как кондишены устроены
  306.            У тебя есть пример кондишена с первым параметром такого же типа, как нам нужно
  307.            У тебя есть пример кондишена, который проверяет текст
  308.            Ты можешь открыть код селенидовского кондишена texts or exactTexts и тоже взять оттуда идеи
  309.            Мы определились с тем, что наши новые кондишены должны делать, с их именами и парамерами
  310.  
  311.        Попробуй написать эти 2 кондишена.
  312.  
  313.        Будет сложно - обращайся, будем упрощать задачу)
  314.    */
  315. ****************************************
  316.    public void visit(){
  317.            open();
  318.    }
  319. /*
  320.     а вот тут - уже вызовешь open(...), указав ему урл нужный
  321.  
  322.     так open(...) - будет гораздо полезнее)
  323. */
  324. **********************************************
  325.     public void goToSent(){
  326.         $(navigation).findElement(By.partialLinkText("Sent")).click();
  327.     }
  328.  
  329.     public void goToInbox(){
  330.         $(navigation).findElement(By.partialLinkText("Inbox")).click();
  331.     }
  332. /*
  333.     вот эти методы  могут быть проблемными
  334.  
  335.     если элементы внутри $(navigation) загружаются не сразу - то и с работой этих методов может быть проблема
  336.  
  337.     если тесты будут падать на этом коде - то можно
  338.     найти локатор By для каждой из линок и использовать
  339.     $(...) - уже для такого локатора
  340.  
  341.     у обоих линок этих (Inbox & Sent)
  342.     можно опереться Title -
  343.  
  344.     если напишешь метод By byTitle(String title) -
  345.     или построишь css selector - который отбирает по Title -
  346.     то эту проблему удастся вот так решить)
  347.  
  348. */
  349.  
  350. ****************************************
  351. $(By.xpath("//*[.='COMPOSE']"))
  352.  
  353. Есть проблема с подиском переменной, пока реализовала через xpath, други вариантов нет(
  354.  
  355. /*
  356.     посмотри как в Selenide устроен метод By byText(...)
  357.     )
  358.    
  359.     внутри него - как раз и используется xpath-выражение)
  360.     правда, более сложное и универсальное
  361.    
  362.     реализуй и ты в ConciseAPI  - такой метод
  363.     и используй его для поиска по тексту
  364.    
  365. */
Advertisement
Add Comment
Please, Sign In to add comment