julia_v_iluhina

Untitled

Nov 8th, 2016
88
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 16.68 KB | None | 0 0
  1. src / test / java / com / tasj / modular_opp / search / GoogleSearchTest.java
  2. src / main / java / com / tasj / modular_oop / search / GoogleSearch.java
  3.  
  4. /*
  5.     корректнее назвать пекеджи search - googlesearch
  6.  
  7.     или структурно
  8.     google
  9.         search
  10.         gmail
  11. */
  12. ****************************************
  13. public interface Condition<V> {
  14.     public abstract V apply(By locator);
  15. }
  16. /*
  17.     public abstract - лишнее
  18.  
  19.     мы в интерфейсах - лишь объявляем методы
  20.     и в классах их будем имплементировать как public
  21.     так что тут
  22.     вместо
  23.     public abstract V apply(By locator);
  24.     достаточно
  25.     V apply(By locator);
  26. */
  27. *********************************
  28. public class MinimumSizeOf implements Condition<Boolean> {
  29. /*
  30.     я бы не реализовывала Condition<Boolean>
  31.     на самом деле, любой из кондишенов - можно реализовать
  32.     либо как
  33.     Condition<WebElement>
  34.     либо как
  35.     Condition<List<WebElement>>
  36.  
  37.     т к по сути - мы всегда - работаем либо со списком, либо с элементом
  38.  
  39.     мы мало выгод получаем от реализации Condition<Boolean>
  40.     сам факт - что проверка кондишена не упала - говорит о том, что да , все ок
  41.  
  42.     да и вот такой вариант -  Condition<Boolean>
  43.     будет требовать дополнительной логики в WaitFor#until
  44.     (мы же не нулл вовращаем в apply, а FAlSE)
  45.     можешь сама посмотреть в селениумском WevDriverWait#until
  46.  
  47.     предлагаю не тратить силы на развитие логики в WaitFor#until
  48.     а кондишены реализовать как Condition<WebElement> или Condition<List<WebElement>>
  49.     это полезнее)
  50. */
  51. *****************************************
  52. public class NthElementText implements Condition {
  53. /*
  54.     этот - реализуй как Condition<List<WebElement>>
  55.  
  56.     это несколько странно)
  57.     но пока так реализуй)
  58.  
  59.     логичнее реализовать - чтоб на вход - мы получали локатор списка
  60.     а возвращали - вебэлемент
  61.     но - это будет нарушать общую картинку)
  62.  
  63.     остальные кондишены - если и получают локатор списка - возвращают список
  64.     если локатор элемента - возвращают элемент
  65.  
  66.     пока по кондишены для todoMVC не думай)
  67.  
  68.     они тоже, такие, гибридные)
  69.  
  70.     мы вскоре и от этого NthElementText избавимся)
  71.     пока - пусть будет  Condition<List<WebElement>>
  72.     вернем в случае успеха - тот же список элементов, что и получили
  73. */
  74. ******************************
  75. public class Size implements Condition {
  76. /*
  77.     вообще во всех кондишенах  - уточни тип у Condition
  78.  
  79.     Condition<WebElement> либо Condition<List<WebElement>>
  80. */
  81. ********************************
  82. public class Url implements Condition {
  83. /*
  84.     а вот такой кондишен не стоит реализовывать)
  85.     странно оперировать локатором - для проверки урла
  86.  
  87.     это проверяй как и ранее - через родной селениусмский кондишен
  88.     можно оставить для этого - ранее реализованный assertThat
  89.  
  90.     за счет разных параметров - конфликтовать с новыми assertThat - старый assertThat не будет )
  91. */
  92. ****************************
  93.     public static <V> V assertCondition(Condition<V> condition){
  94.         return waitFor(null).until(condition);
  95.     }
  96. /*
  97.     и вот этот метод со странной реализацией - уйдет )
  98. */
  99. *************************************
  100.  public static WaitFor waitFor(By locator, long timeout){
  101. /*
  102.     я бы параметр timeout - перенесла в until
  103.  
  104.     а в этом методе - оставила только локатор
  105.     мне кажется это более логичным
  106.  
  107.     для какого элемента/списка ждем
  108.     до каких пор ждем = кондишен + таймаут
  109.  
  110.     как-то более последовательно)
  111. */
  112. ************************************
  113.     catch (StaleElementReferenceException | IndexOutOfBoundsException | ElementNotVisibleException ex) {
  114.         System.out.println(locator);
  115.     }
  116. /*
  117.     посмотри - какие предки есть у исключений
  118.  
  119.     все кроме IndexOutOfBoundsException
  120.     приводятся к WebDriverException
  121.  
  122.     можно ловить именно его - WebDriverException (его потомков мы так тоже поймаем)
  123.     и IndexOutOfBoundsException
  124.  
  125.     выводить это - System.out.println(locator);
  126.     в общем-то мало полезно
  127.  
  128.     а вот запомнить полученную ошибку в переменную
  129.     и затем передать ее вторым параметром в  TimeoutException - будет самое то
  130.     в таком случае  - сообщение об ошибке будет вот такое
  131.     наше сообщение
  132.     caused by ... и описание исключения - причины
  133.  
  134.     такую переменную назови lastError
  135.     используй тип Throwable
  136.  
  137.     http://howtodoinjava.com/best-practices/java-exception-handling-best-practices/
  138.     http://www.developer.com/java/data/best-practices-in-java-exception-handling.html
  139.     https://www.javacodegeeks.com/2013/07/java-exception-handling-tutorial-with-examples-and-best-practices.html
  140.  
  141.  
  142.     https://habrahabr.ru/company/golovachcourses/blog/225585/
  143.  
  144.  
  145. */
  146. *************************
  147.         (new TimeoutException("failed while waiting " + timeout + " seconds to assert " + condition.toString())).printStackTrace();
  148.         return null;
  149. /*
  150.     нам нужно вызвать исключение
  151.     нам нужно - чтоб тест упал) - если проверка не прошла
  152.  
  153.     это делается так - throw new TimeoutException(....)
  154.  
  155.     линки выше - помогут разобраться получше)
  156. */
  157. ****************************************************
  158. /*
  159.     Иерархия для кондишенов у тебя сейчас - достаточно простая
  160.  
  161.     интерфейс
  162.     и классы-кондишены, имплементирующие его
  163.  
  164.     Минимально необходимая реализация есть
  165.  
  166.     Будем ее развивать
  167.  
  168.     Далее - реализуй абстрактный класс-предок AbstractCondition<V> ,
  169.     который имплементирует интерфейс Condition<V>
  170.  
  171.     Статья про нейминг
  172.     http://www.vertigrated.com/blog/2011/02/interface-and-class-naming-anti-patterns-java-naming-convention-tautologies/
  173.  
  174.     Теперь смотрим дальше
  175.     Нам хочется, чтобы наш toString() для любого кондишена был хорошо структурирован
  176.     Это значит, чтобы фразы были типа
  177.  
  178.           __имя кондишена__ +
  179.           for ____element/elements___ found by: ___locator___
  180.           expected ___expected result description_____
  181.           actual ____actual result description_____
  182.  
  183.     Можно конечно в каждом из кондишенов просто строить такую фразу
  184.     согласно правилу
  185.  
  186.     А можно - toString() реализовать в абстрактном классе, и внутри этого метода - вызывать абстрактные методы
  187.     а их уже - реализуем в потомках. Таким образом - структура сообщения любого из кондишенов
  188.     будет одинаковой
  189.  
  190.     где брать ___locator___ тут - мы чуть позже поговорим...
  191.     пока пропусти этот момент
  192.  
  193.     а вот для
  194.         ____element/elements___
  195.         ___expected result description_____
  196.         ____actual result description____
  197.     объяви и используй абстрактные методы
  198.         identity()
  199.         expected()
  200.         actual()
  201.  
  202.     __имя кондишена__
  203.     раз мы будем реализовывать кондишены как отдельные классы - потомки (пока - нашего абстрактного класса)
  204.     то откуда взять имя кондишена - у нас есть
  205.     у нас есть имя класса кондишена - чем не имя )
  206.  
  207.     Далее
  208.     element/elements
  209.     Это только верхушечка айсберга
  210.     Да, схема проверки кондишенов - у нас одна и та же
  211.     Хоть это кондишен для списка элементов
  212.     Хоть для элемента
  213.     И нам нужно, чтоб наш waitUntil был один и работал с любым кондишеном
  214.  
  215.     Но
  216.     Нам важна разница - что это за кондишен - для элемента или коллекции
  217.     В данный момент - чтобы сказать про то в фразе - for ____element/elements
  218.     А далее (в следующих заданиях) - чтобы кондишены для element - мы просто  НЕ МОГЛИ применить к elements
  219.     Таким образом, приходим к тому, что у нашего общего предка AbstractCondition<V>
  220.     Будут 2 абстрактных потомка
  221.         CollectionCondition extends AbstractCondition<List<WebElement>>
  222.         ElementCondition extends AbstractCondition<WebElement>
  223.     От которых мы будем наследовать наши реальные кондишены
  224.  
  225.     И тогда, стоит держать 2 класса для реализации статических методов - вызовов кондишенов
  226.     CollectionConditions и  ElementConditions
  227.         это будут классы-контейнеры статических методов
  228.         типа
  229.         public static Condition<WebElement> visible() {
  230.             return new Visible();
  231.         }
  232.         чтобы уже в коде  - не писать - new Visible()
  233.  
  234.     С иерархией разобрались немного )
  235.  
  236.     Возвращаемся к фразе в toString()
  237.         Если этот метод реализовать в главном предке AbstractCondition,
  238.         и этот метод будет использовать абстрактные методы, возвращающие строки
  239.         для всех элементов этой фразы
  240.         То структура сообщения о кондишене - будет всегда четкой
  241.  
  242.     А нам останется - реализовать эти абстрактные методы, возвращающие строки
  243.     в потомках
  244.     Тут смотри внимательно
  245.     Некоторые из методов надо будет реализовать уже в кондишенах-потомках
  246.     Некоторые - в CollectionCondition и ElementCondition
  247.  
  248.     Руководствуйся такими рассуждениями
  249.     Если во всех потомках я пишу одинаковый код
  250.     То лучше этот код написать в предке
  251.  
  252.     Что касается типа параметра condition для
  253.     until(Condition<V> condition)
  254.  
  255.     Ты можешь указать интерфейс Condition<V>
  256.  
  257.     И метод будет корректно работать для любого из кондишенов
  258.     Т к этот интерфейс лежит в основе этой иерархии
  259. */
  260.  
  261. ****************************************
  262. /*
  263.     еще один наворот внутри кондишенов)
  264.  
  265.     мы его впоследствии переделаем
  266.  
  267.     сейчас нам это нужно для лучшего понимания процесса
  268.  
  269.     в apply передают локатор
  270.     описание которого мы возвращаем в одном из методов кондишена (для ToString)
  271.     и это - справедливо для всех кондишенов
  272.  
  273.     и нам - еще в AbstractCondition интересно сохранить этот локатор
  274.  
  275.     потому в AbstractCondition заводим переменную locator
  276.     и реализуем метод apply
  277.     в котором
  278.         сохраняем переданный в apply локатор
  279.         и вызываем абстрактный метод check
  280.         (- который, собственно, и нужно будет в кондишенах реализовывать вместо apply)
  281.  
  282.     check - будет делать то же, что и  apply делал ранее
  283.     нам  это нужно было для того, чтоб локатор получить еще на уровне абстрактного класса
  284.  
  285.     теперь - и в toString - мы можем подправить фразу - про локатор
  286.  
  287.     сразу подумай, какой модификатор доступа использовать для такой переменной
  288.     http://www.quizful.net/interview/java/access-modifiers
  289.  
  290.     но это опять была только верхушка айсберга)
  291.  
  292.     посмотри на реализованные кондишены
  293.     первой строкой в методе проверок - у тебя идет
  294.     List<WebElement> elements = getDriver().findElements(elementsLocator);
  295.     или
  296.     WebElement element = getDriver().findElement(elementsLocator);
  297.     (таких, кстати, пока нету
  298.         реализуй
  299.         visible
  300.         present
  301.         text
  302.         exactText
  303.     )
  304.  
  305.     Так вот
  306.     фактически - вот это
  307.     List<WebElement> elements = getDriver().findElements(elementsLocator);
  308.     или
  309.     WebElement element = getDriver().findElement(elementsLocator);
  310.  
  311.     это сущность типа V с точки зрения класса AbstractCondition
  312.  
  313.     давай метод check изменим
  314.     пусть принимает не локатор
  315.     а уже V entity (т е внутри кондишена в реализации check
  316.     нам ничего не придется искать по локатору - нам это уже на вход передадут)
  317.  
  318.     а вот в реализации apply в AbstractCondition
  319.     для получения этого V entity
  320.     мы объявим новый абстрактный метод getWrappedEntity()
  321.     который будет нам возвращать значение типа V
  322.  
  323.     а реализуем его в классах CollectionCondition и ElementCondition
  324.  
  325.     думаю, ты догадаешься, как )
  326.  
  327.     а вот потом, когда у нас будут наши классы для элементов (следующее задание)
  328.     мы будем в apply передавать не локатор
  329.     а сам элемент нашего нового класса
  330.     и сам элемент будет возвращать getWrappedEntity()
  331.     и мы тут, в кондишенах, избавимся от  getWrappedEntity() и его реализаций )
  332.  
  333.     пока это такой костыль
  334.     нарушающий принцип Single Responsibility
  335.     но позволяющий нам сейчас максимально реализовать код
  336.     который впоследствии изменим минимально
  337. */
Advertisement
Add Comment
Please, Sign In to add comment