julia_v_iluhina

Untitled

Oct 6th, 2016
99
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 18.85 KB | None | 0 0
  1. public class Configuration {
  2.     public  static int timeout = 35;
  3. }
  4. /*
  5.     тут - утанавливаем значение по умолчанию
  6.     это - такое значение, которое подходит для большинства
  7.  
  8.     в селениде - это было 4 секунды
  9.     предлагаю и нам тут именно 4 секунды прописать
  10.  
  11.  
  12.     а уже в тест-классе - укажешь 35 секунд
  13.     вспомни - как мы это делали в селенидовском решении
  14.  
  15.     тут - аналогично
  16. */
  17. ************************************
  18.  
  19. public static ExpectedCondition<Boolean> nthElementHasText(final List<WebElement> elements , final int index, final String text) {
  20. /*
  21.     реализовывать этот кондишен как ExpectedCondition<Boolean> - пользы мало
  22.     я бы реализовала его как
  23.     ExpectedCondition<WebElement> - тогда apply возвращал бы в случае успеха вебэлемент с нужным текстом
  24.     (или null - в случае не успеха)
  25.     или
  26.     ExpectedCondition<List<WebElement>> - тогда apply возвращал бы в случае успеха список веб элементов
  27.     (тот же, что пришел на вход)
  28.  
  29.     в таком случае можно было бы воспользоваться результатом, который вернет assertThat для єтого кондишена
  30. */
  31.         return new ExpectedCondition<Boolean>() {
  32.             private List<WebElement> copyElements = elements;
  33.             /*
  34.                 хитро придумал)
  35.                 только надо доработать эту идею
  36.  
  37.                 во-первых - ты пока завел переменную, которая не новый список-копия
  38.                 а которая указвает на тот же лейзи прокси список
  39.                 т е - ты не ушел от того - что список лейзи прокси
  40.  
  41.                 как копировать списки
  42.                 http://stackoverflow.com/questions/689370/java-collections-copy-list-i-dont-understand
  43.                 http://stackoverflow.com/questions/14319732/how-to-copy-a-java-util-list-into-another-java-util-list
  44.  
  45.                 еще момент
  46.                 мы скопируем ЕДИНОЖДЫ этот список = завиксируем состояние
  47.                 и потом многократно вызовем apply
  48.                 в котором будем проверять не истинное положение дел
  49.                 а вот  то,первое зафиксированное состояние
  50.  
  51.                 вывод - вот такая операция - должна происходить не при инициализации кондишена
  52.                 а в начале выполнения apply
  53.  
  54.                 и все же больше пользы было бы именно в списке текстов
  55.                 а не списке элементов
  56.                 хотя и мысль красивая)
  57.                 ниже поясню
  58.             */
  59.  
  60.             public Boolean apply(WebDriver driver) {
  61.                 if (!copyElements.get(index).getText().contains(text)){
  62.                     return false;
  63.                 }
  64.                 return true;
  65.                 /*
  66.                     можно это же написать проще
  67.                     return (copyElements.get(index).getText().contains(text))
  68.  
  69.                     но - лучше так не делать
  70.                     тут - самое время зафиксировать факт(actual) - который позже выведем в toString()
  71.  
  72.                     какой у нас факт - это текст такого-то элемента
  73.                     нужно что-то такое
  74.                     actualText = elements.get(index).getText();
  75.                     и уже ниже - return (actualText.contains(text))
  76.                     и этот же actualText - выведем и в toString
  77.  
  78.                     это даст тебе возможность писать простой toString
  79.                     который уже ничего не ищет
  80.                     просто - выводит то, что ранее получено
  81.  
  82.                     теперь давай рассудим - что нам бы было удобно увидеть в сообщении об ошибке
  83.                     я, например, хотела бы увидеть не только текст такого-то элемента
  84.                     но и все тексты всех элементво в списке
  85.                     чтобы понять - может я в индексе ошиблась
  86.                     и вот для этого - в начале apply и стоило бы собрать список строк - тексты всех элементов
  87.                     чтобы потом - для принятия решения - им оперировать
  88.                     и в  toString вывести
  89.  
  90.                     ну и далее размышляем
  91.                     если мы выводим и анализируем лишь actual текст такого-то элемента
  92.                     то мы вообще копию списка можем не делать
  93.                     достаточно зафиксировать actual текст такого-то элемента
  94.  
  95.                     а если выводим все тексты и анализируем такой-то текст - то нам удобнее все же
  96.                     оперировать списком текстов, а не копией списка
  97.  
  98.                     поэтому - как ни красива эта идея - с копированием списка
  99.                     нам она тут не пригодится)
  100.  
  101.                     да, и пока не торопись реализовывать работу со списком текстов
  102.                     читай дальше - поясню почему
  103.                 */
  104.             }
  105.  
  106.             public String toString() {
  107.                 return String.format("\nExpected text: %s\n while actual text is: %s\n", text, copyElements.get(index).getText());
  108.             }
  109.         };
  110.     }
  111. /*
  112.     еще момент
  113.  
  114.     когда мы выполняем elements.get(index)
  115.     для индекса за границами списка
  116.     может возникнуть  IndexOutOfBoundsException
  117.     и в принципе - при работе с элементами могут возникать исключения типа StaleElementReferenceException или
  118.     ElementNotVisibleException
  119.  
  120.     и их надо внутри apply кондишена - ловить
  121.  
  122.     чтобы упростить apply кондишена - можно воспользоваться рекомендациями
  123.     https://docs.google.com/document/d/1BiYTLdypDfucSqiY9isv1HCKKQIxelzqYrN-3Ku1RWM/edit?usp=sharing
  124.  
  125.     в качестве типа параметра для кетчера можешь использовать тип попроще
  126.     не
  127.     final Function<? super WebDriver, V> condition
  128.     а
  129.     ExpectedCondition<V> condition
  130.  
  131.     final Function<? super WebDriver, V> - это предок ExpectedCondition
  132.     нам не обязательно оперировать им
  133.  
  134.     мы кетчер только для кондишенов будем использовать
  135. */
  136.  
  137. http://joxi.ru/Vrwqg81HK6dYR2
  138.  
  139. /*
  140.     Вот еще пример реализации (мне в toString не нравится вывод (index+1), а не просто index,
  141.     но это уже детали)
  142.  
  143.     1 - применили elementExceptionsCatcher
  144.     цель - избавиться от try-catch в самом apply
  145.  
  146.     это нам надо для того, чтобы упростить логику apply, увидеть ее без лишней мишуры
  147.     научи elementExceptionsCatcher ловить и IndexOutOfBoundsException
  148.  
  149.     кстати - можно ловить несколько видов исключений в одной catch-секции
  150.     так можно и в кетчере это сделать)
  151.     http://stackoverflow.com/questions/3495926/can-i-catch-multiple-java-exceptions-in-the-same-catch-clause
  152.  
  153.     тоже тонкость)
  154.     если выполнять return elements.get(index); -
  155.     список же может опять переискаться) и вылезет что-то другое... ((
  156.  
  157.     как выкручиваемся
  158.         2 - сохраняем актуальный текст нужного нам элемента в этой переменной
  159.         3 - сначала получаем сам элемент (он уже не переискивается - он не лейзи прокси)
  160.         4 - у него получаем текст
  161.         5 - сверяем полученный текст
  162.         6 - возвращаем элемент из пункта 3 (не заново ищем в списке, а возвращаем тот же, по которому делали выводы)
  163.         7 - в тексте ошибки оперируем только актуальным текстом, который мы получили в пункте 4 (заново не получаем)
  164.  
  165.     при таких раскладах - если кондишен реализован как ExpectedCondition<WebElement>
  166.     нам действительно не стоит получать все тексты
  167.     когда будем переписывать  - избавляться от лейзи прокси элементов
  168.     то сможешь получить тексты элементов и вывести их все в toString
  169.  
  170.     тут - с лейзи прокси - чтобы так реализовать - придется глубже в дебри залезть
  171.     и таки делать еще и копию списка вебэлементов
  172.     не хочется)
  173.  
  174.     выводы
  175.         8 - возвращаем ровно тот же элемент, текст которого проверяли
  176.         9 - описываем проверенный в apply текст
  177. */
  178. *****************************************************
  179. public static ExpectedCondition<List<WebElement>> texts(final List<WebElement> elements , final String... expectedTexts) {
  180.  
  181.         return new ExpectedCondition<List<WebElement>>() {
  182.  
  183.             public List<String> actualTexts = new ArrayList<String>();
  184.  
  185.             public String str1 = "";
  186.             public String str2 = "";
  187.             /*
  188.                 эти 2 переменные тебе не нужны
  189.             */
  190.  
  191.             public List<WebElement> apply(WebDriver driver) {
  192.             /*
  193.                 сначала  - очищай actualTexts или заново инициализируй
  194.  
  195.                 несколько вызовов apply - и в списке - бардак)
  196.             */
  197.                 for(int i = 0; i < elements.size(); i++ ){
  198.                     actualTexts.add(i, elements.get(i).getText());
  199.                 }
  200.              /*
  201.                 этот цикл будет легче - если применишь
  202.                 for(WebElement element:elements)
  203.              */
  204.                 if (actualTexts.size() == expectedTexts.length){
  205.                     for(int i = 0; i < actualTexts.size(); i++ ) {
  206.                         if (!actualTexts.get(i).contains(expectedTexts[i])) {
  207.                             return null;
  208.                         }
  209.                     }
  210.                 } else {
  211.                     return null;
  212.                 }
  213.                 return elements;
  214.                 /*
  215.                     этот кусочек можно переписать чуть проще
  216.                     ниже поясню
  217.                 */
  218.             }
  219.  
  220.             public String toString() {
  221.                 for(int i = 0; i < actualTexts.size(); i++){
  222.                     str1 += actualTexts.get(i);
  223.                 }
  224.                 /*
  225.                     у списка строк - красивое текстовое представление
  226.                     actualTexts.toString() - уже выведет все элементы
  227.                 */
  228.                 for(int i = 0; i < expectedTexts.length; i++){
  229.                     str2 += expectedTexts[i];
  230.                 }
  231.                 /*
  232.                     по сути varargs параметр - это практически массив
  233.                     http://www.linkex.ru/java/varargs.php
  234.  
  235.                     у массива - не крисивое текстовое представление
  236.                     expectedTexts.toString() - будет не красиво
  237.                     а вот Arrays.toString(expectedTexts) - будет ок)
  238.  
  239.                     таким образом - код будет проще)
  240.                 */
  241.                 return String.format("\nChecked that expected container: %s\n not equal to actual container: %s\n Containers not equal", str2, str1);
  242.             }
  243.         };
  244.     }
  245. ******************************************
  246.     http://joxi.ru/ZrJX8Y3f14Zoz2
  247.     /*
  248.         вот вариант реализации
  249.         в принципе - у тебя уже похоже все
  250.         применение кетчера + немного логика упрощена + фраза в toString - попроще)
  251.  
  252.         1-2-3 - этот кондишен делаем как ExpectedCondition<List<WebElement>>
  253.  
  254.         4 - переменную actualTexts объявляем внутри анонимного класса, а не просто в методе
  255.          причины - только внутри реализации кондишена actualTexts и нужна
  256.  
  257.         5 - actualTexts - всегда инициализируем вначале apply
  258.         причина - каждый вызов  apply - проверка заново
  259.         надо оперировать свежими данными
  260.  
  261.         6 - у нас ExpectedCondition<List<WebElement>>
  262.         когда проверка прошла - в случае успеха мы возвращаем тот же лейзи-прокси список
  263.  
  264.         7 - когда проверка не прошла - возвращаем нулл
  265.  
  266.         8 - в toString() - используем тот же список текстов, что сохранили в actualTexts
  267.         apply - когда принимали решение - проверка прошла или нет
  268.     */
  269. *****************************
  270. http://joxi.ru/krDOZldF0pJoeA
  271.  
  272. /*
  273.     размести эти классы в пекедже core
  274.     core & pages - будут на одном уровне
  275. */
  276. *************************************
  277. public class GMailPage{
  278.  
  279.     @FindBy(css = "[role='main'] .zA")
  280.     public List<WebElement> mail;
  281.     /*
  282.         вот это - как раз mails )
  283.  
  284.  
  285.     */
  286.  
  287.     @FindBy(css = "[role='main']")
  288.     public List<WebElement> mails;
  289.     /*
  290.         а такой список элементов - тебе не нужен )
  291.     */
  292.  
  293.     public GMailPage(WebDriver driver){
  294.         PageFactory.initElements(driver, this);
  295.     }
  296.     /*
  297.         с конструктором - все ок
  298.  
  299.         только я бы в пейдже - разместила все вспомогательные методы
  300.  
  301.         а еще лучше
  302.         организовать предка для пейджа
  303.         с переменной WebDriver driver
  304.         и в конструкторе - выполнять PageFactory.initElements(driver, this);
  305.         и запоминать в переменной driver - переданный в конструктор driver
  306.         https://docs.oracle.com/javase/tutorial/java/javaOO/classvars.html
  307.  
  308.         тогда - и внутри пейджей-наследников такого класса
  309.         сможешь использовать методы, которым надо передать драйвер
  310.         как реализовать конструктор в классах-наследниках - почитай тут
  311.         http://developer.alexanderklimov.ru/android/java/extends.php
  312.  
  313.  
  314.         подсмотри в решении селенидовском - разбивку на пейджи
  315.         будут пейджи-объекты теперь
  316.         но логика размещения методов, их параметры, идеи в названиях пейджей -
  317.         все это можно использовать
  318.     */
  319. }
  320. ************************
  321. public class BaseTest {
  322.  
  323.     ...
  324.     public static WebDriverWait wait;
  325.     /*
  326.         тебе не нужна эта переменная
  327.         у нас есть assertThat - и это будем использовать
  328.     */
  329. **************************************
  330. public class GMailTest extends BaseTest {
  331.     @BeforeClass
  332.     public static void config() {
  333.         Configuration.timeout = 15;
  334.     }
  335.     /*
  336.         о, так ты так и делаешь - настраиваешь тут таймаут
  337.         чего тогда такой огромный таймаут по умолчанию? )
  338.     */
  339. ******************************************
  340.     GMailPage page = new GMailPage(driver);
  341.     /*
  342.         да, вот таким способом и остальный пейджи создашь
  343.     */
  344. *********
  345.     public void assertMail(int  index, String mailHeaderText){
  346.         assertThat(driver, nthElementHasText(page.mail, index, mailHeaderText));
  347.     }
  348. /*
  349.     тут все ок с реализацией
  350. */
  351. *******************
  352.     public void assertMails(String...mailHeaderText){
  353.         assertThat(driver, texts(page.mails, mailHeaderText));
  354.     }
  355. /*
  356.     а тут почему работаешь со списком элементов по слелектору [role='main']?
  357.     нам надо по-прежнему работать с [role='main'] .zA
  358.    
  359.     имя параметра метода
  360.     метод позволяет работать с текстАМИ заголовков мейлов
  361.     mailHeaderText__s__
  362.     )
  363. */
Advertisement
Add Comment
Please, Sign In to add comment