julia_v_iluhina

Untitled

Sep 21st, 2016
85
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 15.01 KB | None | 0 0
  1.  protected static <T> T waitUntil(By locator, Condition<T> condition, long timeoutMs)
  2.  ...
  3.  public static <V> V assertThat(By locator, Condition<V> condition) {
  4.     return assertThat(locator, condition, Configuration.timeout);
  5.  }
  6.  ...
  7.  public class Configuration {
  8.     public static long timeout = 4;
  9.  ...
  10. /*
  11.     следи за размерностью таймаута )
  12.  
  13.     waitUntil - хочет миллисекунды
  14.  
  15.     assertThat - передает - 4 миллисекунды
  16.  
  17.     так что - все ждет))) 4 миллисекунды
  18.  
  19.     красивое решение - прийти к таймауту одной размерности - везде в проекте
  20.     чтоб не думать - где пересчитывать, а где не пересчитывать
  21.  
  22.     ну и в самом тест-классе - не мешало бы увеличить таймаут по умолчанию
  23.     вспомни - мы до 15 секунд, а то и до всех 20 увеличивали
  24.  
  25.     заодно - обеспечь одинаковое название для понятия - таймаут
  26.  
  27.     но и это еще не все)
  28. */
  29.  
  30. NoSuchElementException
  31.  
  32. /*
  33.     с такой ошибкой тест начинает падать - буквально на попытке нажать compose
  34.  
  35.     и это исключение лови в waitUntil
  36.  
  37.     после этого тест задаботает
  38. */
  39. **************************************
  40. CustomConditions
  41. /*
  42.     уже не нужен
  43.     прибивай
  44.  
  45.     ходить подсматривать логику кондишенов - будешь в другой свой репозиторий)
  46.  
  47. */
  48. ********************************
  49. public abstract class Condition <T> {
  50. /*
  51.     переноси в пекедж conditions
  52.  
  53.     кстати - пекеджи называют маленькими буквами
  54.     https://google.github.io/styleguide/javaguide.html#s5.2.1-package-names
  55.  
  56.     могут быть сложности с тем, чтоб зафиксировать это в репозитории
  57.  
  58.     когда ты меняешь лишь регистр буквы в названии -
  59.     с точки зрения репозитория ничего не поменялось  (case insensitive)
  60.     вот полезные линки про эту проблему
  61.     https://www.patrick-wied.at/blog/rename-files-and-folders-with-git
  62.     http://stackoverflow.com/questions/8481488/is-git-not-case-sensitive
  63.     http://stackoverflow.com/questions/17683458/how-do-i-commit-case-sensitive-only-filename-changes-in-git
  64.     http://stackoverflow.com/questions/8904327/case-sensitivity-in-git
  65.     http://stackoverflow.com/questions/3011625/git-mv-and-only-change-case-of-directory
  66.  
  67.  
  68.     если это сложно, то можно поступить так
  69.  
  70.       если надо поменять лишь регистр буквы в названии (pageObject -> pageobject)
  71.       и отразить эти изменения в репозитории
  72.  
  73.       1)добавляем к названию еще какую-нибудь букву/цифру (pageObject -> pageObject1)
  74.       2)обновляем репозиторий
  75.       3)корректируем название на нужный нам вариант (pageObject1 -> pageobject)
  76.       4)обновляем репозиторий
  77.  
  78.       таким образом - изменения в регистре букв будут корректно отражены в репозитории
  79.       т к каждый раз названия менялись не только за счет регистра букв
  80. */
  81. ********************************
  82.  
  83. /*
  84.     хорошая идея - реализовать умное ожидание в отдельном классе
  85.     с точки зрения Single Responsibility - так будет лучше
  86.  
  87.     наглядно этот класс назвать WaitFor
  88.     а статический метод-умный ожидатель выполнения кондишена - until
  89.     и в коде мы будем писать waitFor(byCss(...)).until(visible())
  90.     получится очень наглядная и понятная фраза
  91.  
  92.     в том же классе - расположи и метод sleep
  93.     а его сделай - private
  94.     т к sleep будет нужен только для реализации ждущей проверки
  95.  
  96.     чтобы так писать - waitFor(byCss(...)).until(visible())
  97.         реализуй конструктор с параметром By locator
  98.  
  99.         реализуй статический метод waitFor с параметром By locator
  100.         возвращающий - новый объект класса WaitFor
  101.  
  102.         реализуй метод until(...)
  103.     получишь
  104.        waitFor(byCss(...)). - создали объект типа WaitFor
  105.           until(visible()) - вызвали у него метод until
  106.  
  107.     конечно, until-у передаай как кондишен, так и таймаут
  108.     уже второй вариант  until-а - без таймаута (также как и раньше - такой берет таймаут по умолчанию
  109. */
  110. ******************
  111.  throw new TimeoutException("", lastError);
  112. /*
  113.     про сообщение об ошибке в until
  114.     failed while waiting ... seconds
  115.     to assert __condition___
  116.  
  117.      __condition___ - это как раз toString кондишена
  118. */
  119. **********************
  120.             catch (NoSuchElementException| StaleElementReferenceException | ElementNotVisibleException | IndexOutOfBoundsException e) {
  121. /*
  122.     посмотри - какие предки есть у исключений
  123.  
  124.     все кроме IndexOutOfBoundsException
  125.     приводятся к WebDriverException
  126.  
  127.     можно ловить именно его - WebDriverException (его потомков мы так тоже поймаем)
  128.     и IndexOutOfBoundsException
  129. */
  130. ************************************
  131.  
  132. /*
  133.     Иерархия для кондишенов у тебя сейчас - достаточно простая
  134.  
  135.     интерфейс
  136.     и классы-кондишены, имплементирующие его
  137.  
  138.     Минимально необходимая реализация есть
  139.  
  140.     Будем ее развивать
  141.  
  142.     Далее - реализуй абстрактный класс-предок AbstractCondition<V> ,
  143.     который имплементирует интерфейс Condition<V>
  144.  
  145.     Статья про нейминг
  146.     http://www.vertigrated.com/blog/2011/02/interface-and-class-naming-anti-patterns-java-naming-convention-tautologies/
  147.  
  148.     Теперь смотрим дальше
  149.     Нам хочется, чтобы наш toString() для любого кондишена был хорошо структурирован
  150.     Это значит, чтобы фразы были типа
  151.  
  152.           имя кондишена +
  153.           for ____element/elements___ found by: ___locator___
  154.           expected ___expected result desription_____
  155.           actual ____actual result description
  156.  
  157.     Можно конечно в каждом из кондишенов просто строить такую фразу
  158.     согласно правилу
  159.     А можно - toString() реализовать в абстрактном классе, и внутри этого метода - вызывать абстрактные методы
  160.     а их уже - реализуем в потомках. Таким образом - структура сообщения любого из кондишенов
  161.     будет одинаковой
  162.  
  163.     Имя кондишена
  164.     раз мы будем реализовывать кондишены как отдельные классы - потомки (пока - нашего абстрактного класса)
  165.     то откуда взять имя кондишена - у нас есть
  166.     у нас есть имя класса кондишена - чем не имя )
  167.  
  168.     Далее
  169.     element/elements
  170.     Это только верхушечка айсберга
  171.     Да, схема проверки кондишенов - у нас одна и та же
  172.     Хоть это кондишен для списка элементов
  173.     Хоть для элемента
  174.     И нам нужно, чтоб наш waitUntil был один и работал с любым кондишеном
  175.  
  176.     Но
  177.     Нам важна разница - что это за кондишен - для элемента или коллекции
  178.     В данный момент - чтобы сказать про то в фразе - for ____element/elements
  179.     А далее (в следующих заданиях) - чтобы кондишены для element - мы просто  НЕ МОГЛИ применить к elements
  180.     Таким образом, приходим к тому, что у нашего общего предка AbstractCondition<V>
  181.     Будут 2 абстрактных потомка
  182.         CollectionCondition extends AbstractCondition<List<WebElement>>
  183.         ElementCondition extends AbstractCondition<WebElement>
  184.     От которых мы будем наследовать наши реальные кондишены
  185.  
  186.     И тогда, стоит держать 2 класса для реализации статических методов - вызовов кондишенов
  187.     CollectionConditions и  ElementConditions
  188.         это будут классы-контейнеры статических методов
  189.         типа
  190.         public static Condition<WebElement> visible() {
  191.             return new Visible();
  192.         }
  193.         чтобы уже в коде  - не писать - new Visible()
  194.  
  195.     С иерархией разобрались немного )
  196.  
  197.     Возвращаемся к фразе в toString()
  198.         Если этот метод реализовать в главном предке AbstractCondition,
  199.         и этот метод будет использовать абстрактные методы, возвращающие строки
  200.         для всех элементов этой фразы
  201.         То структура сообщения о кондишене - будет всегда четкой
  202.  
  203.     А нам останется - реализовать эти абстрактные методы, возвращающие строки
  204.     в потомках
  205.     Тут будь внимательной
  206.     Некоторые из методов надо будет реализовать уже в кондишенах-потомках
  207.     Некоторые - в CollectionCondition и ElementCondition
  208.  
  209.     Руководствуйся такими рассуждениями
  210.     Если во всех потомках я пишу одинаковый код
  211.     То лучше этот код написать в предке
  212.  
  213.     Что касается типа параметра condition для
  214.     until(Condition<V> condition)
  215.  
  216.     Ты можешь указать интерфейс Condition<V>
  217.  
  218.     И метод будет корректно работать для любого из кондишенов
  219.     Т к этот интерфейс лежит в основе этой иерархии
  220. */
  221. ***************************************************
  222. /*
  223.     еще один наворот внутри кондишенов)
  224.  
  225.     мы его впоследствии переделаем
  226.  
  227.     сейчас нам это нужно для лучшего понимания процесса
  228.  
  229.     в apply передают локатор
  230.     описание которого мы возвращаем в одном из методов кондишена (для ToString)
  231.     и это - справедливо для всех кондишенов
  232.  
  233.     потому в AbstractCondition заводим переменную locator
  234.     в которую сохраняем переданный в apply локатор
  235.  
  236.     и уже в методе, возвращающем описание локатора,
  237.     оперируем этой переменной
  238.  
  239.     сразу подумай, какой модификатор доступа использовать для такой переменной
  240.     http://www.quizful.net/interview/java/access-modifiers
  241.  
  242.     но это опять была только верхушка айсберга)
  243.  
  244.     посмотри на реализованные кондишены
  245.     первой строкой в методе проверок - у тебя идет
  246.     List<WebElement> elements = getDriver().findElements(elementsLocator);
  247.     или
  248.     WebElement element = getDriver().findElement(elementsLocator);
  249.     (таких, кстати, пока нету
  250.         реализуй
  251.         visible
  252.         present
  253.         text
  254.         exactText
  255.     )
  256.  
  257.     Так вот
  258.     фактически - вот это
  259.     List<WebElement> elements = getDriver().findElements(elementsLocator);
  260.     или
  261.     WebElement element = getDriver().findElement(elementsLocator);
  262.  
  263.     это сущность типа V с точки зрения класса AbstractCondition
  264.  
  265.     давай метод check изменим
  266.     пусть принимает не локатор
  267.     а уже V entity (т е внутри кондишена в реализации check
  268.     нам ничего не придется искать по локатору - нам это уже на вход передадут)
  269.  
  270.     а вот в реализации apply в AbstractCondition
  271.     для получения этого V entity
  272.     мы объявим новый абстрактный метод getWrappedEntity()
  273.     который будет нам возвращать значение типа V
  274.  
  275.     а реализуем его в классах CollectionCondition и ElementCondition
  276.  
  277.     думаю, ты догадаешься, как )
  278.  
  279.     а вот потом, когда у нас будут наши классы для элементов (следующее задание)
  280.     мы будем в apply передавать не локатор
  281.     а сам элемент нашего нового класса
  282.     и сам элемент будет возвращать getWrappedEntity()
  283.     и мы тут, в кондишенах, избавимся от  getWrappedEntity() и его реализаций )
  284.  
  285.     пока это такой костыль
  286.     нарушающий принцип Single Responsibility
  287.     но позволяющий нам сейчас максимально реализовать код
  288.     который впоследствии изменим минимально
  289. */
Advertisement
Add Comment
Please, Sign In to add comment