julia_v_iluhina

Untitled

Aug 26th, 2016
95
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 18.06 KB | None | 0 0
  1. http://joxi.ru/a2X3dZMsy6l59m
  2.  
  3. /*
  4.     предка тест-классов - перенеси на уровень выше - раз используется для gmail & google searsh
  5. */
  6. ************************************************
  7.     getWebDriver().findElement(By.name("q")).clear();
  8.     getWebDriver().findElement(By.name("q")).sendKeys(queryText + Keys.ENTER);
  9. vs
  10.     $(By.name("q")).clear();
  11.     $(By.name("q")).sendKeys(queryText + Keys.ENTER);
  12. /*
  13.     не забывай - есть способ писать код попроще)
  14. */
  15. *******************************************************
  16.  
  17.  catch (StaleElementReferenceException | ElementNotVisibleException | IndexOutOfBoundsException e){
  18.  }
  19.  ...
  20.  throw new ElementNotFoundException(String.format("Condition %s not achieved while waiting with timeout of %s, Ms", condition.toString(), timeoutMs), "", "");
  21.  
  22.  
  23.  /*
  24.     вместо ElementNotFoundException - грамотнее использовать selenium.TimeoutException
  25.     (будь внимательна при импорте, с таким именем - есть несколько вариантов)
  26.     именно такое исключение кидает сам селениум - в его new WebDriverWait(...).until(...)
  27.     да и по смыслу - это ближе - не хватило таймаута дождаться того-то
  28.     чуть проще для восприятия будет вот такая фраза
  29.     "failed while waiting ... seconds to assert ...."
  30.  
  31.     catch-секция
  32.  
  33.         Тут можно написать код покороче
  34.  
  35.             зажав ctrl кликай на именах классов кондишенов
  36.             ты увидишь
  37.             что StaleElementReferenceException и ElementNotVisibleException - потомки WebDriverException
  38.  
  39.             потому - можно ловить WebDriverException и IndexOutOfBoundsException
  40.  
  41.         также - в catch-секции сохраняй ошибку в переменной lastError
  42.             чтобы при вызове исключения - включить информацию об ошибке, в результате которой кондишен не прошел
  43.             получим
  44.                 throw new TimeoutException("....", lasterror);
  45.  
  46.  
  47.             помнишь ошибки в Selenide
  48.               ...some error...
  49.               caused by ..... another error ....
  50.  
  51.             вот такое мы получим, если
  52.                 передадим вызываемому исключению не только текст-описание,
  53.                 но и второй параметр - cause = что было причиной того, что проверка не прошла
  54.  
  55.         подробности по lastError
  56.             для этого - объяви вначале метода переменную lastError типа Throwable
  57.                 про Throwable - http://www.quizful.net/post/java-exceptions
  58.  
  59.             и инициализируй ее значением null
  60.                 мы тут без этого не обойдемся
  61.                 http://stackoverflow.com/questions/16699593/uninitialized-object-vs-object-initialized-to-null
  62.                 цитата - Note that the above rule excludes local variables: they must be initialized explicitly,
  63.                 otherwise the program will not compile.
  64.  
  65.         кстати, убери
  66.         throws WebDriverException - в заголовке метода until
  67.  */
  68. ************************************
  69.  
  70. private void sleep(int milliseconds)
  71.  
  72. /*
  73.     молодец, что расположила такой метод в классе WaitFor
  74.     и реализовала его как private
  75.  
  76.     все верно, лучше в руки такое не отдавать))
  77.     только внутри ждущей проверки нам это и надо
  78. */
  79. ***********************************
  80.  
  81. http://joxi.ru/brRlV57uQ9LpQ2
  82.  
  83. /*
  84.     структура пекеджа core
  85.     уже тяжело)
  86.  
  87.     чуть ее разовьем))
  88.  
  89.     в корне core - оставим 1-4
  90.  
  91.     для кондишенов - создай в рамках core пекедж conditions
  92.     туда перемести 5-8
  93.     9 - в итоге вообще уйдет, давай такие вещи тоже отдельно собирать
  94.     например в пекедже core \ deprecated
  95. */
  96. ******************************************
  97.  
  98. /*
  99.     ты писала в слеке, и сейчас это все еще есть -
  100.     проверки кондишенов Condition<Boolean> - не падают
  101.  
  102.     см на код родного селениумского until
  103. */
  104. public <V> V until(Function<? super T, V> isTrue) {
  105.   ...
  106.         V value = isTrue.apply(input);
  107.         if (value != null && Boolean.class.equals(value.getClass())) {
  108.           if (Boolean.TRUE.equals(value)) {
  109.             return value;
  110.           }
  111.         } else if (value != null) {
  112.           return value;
  113.         }
  114.   ...
  115. /*
  116.     видишь - тут танцы вокруг булеана танцуют
  117.     не самые красивые и не самые простые
  118.     я советую так не делать
  119.  
  120.     лучше - если все кондишены будут возвращать нулл - если проверка не прошла
  121.     тем более - что
  122.     у нас так устроен WaitFor - что мі ждущую проверку делаем всегда
  123.     либо для элемента, либо для списка элементов (передаем конечно - локатор, но в итоге - элемент или список)
  124.     потому - для нас будет разумно - если все кондишены - будут
  125.     или Condition<List<WebElement>>, или Condition<WebElement>
  126.     удобно после прошедшей проверки - получить актуальное проверенное - или элемент, или сущность
  127.  
  128.     потому
  129.     в реализованных кондишенах - перейди на вриант Condition<List<WebElement>>, или Condition<WebElement>
  130.     реализуй кондишен Condition<WebElement> Visible - проверку видимости элемента
  131.  
  132.     а раз так - мы в кондишенах всегда будем кидать null  - если условие не будет выполнено
  133.     и так - мы уйдем от проблемы, что сейчас есть
  134. */
  135. /*
  136.     Перейди в ConciseAPI на использование кондишена нашего вместо visibilityOfElementLocated
  137.  
  138.     погоняй google search в полной реализации -
  139.     и так, чтобы проверки по кондишенам падали
  140.     и так, чтоб не падали )
  141.  
  142.     это же надо будет сделать и по финишу)
  143.  
  144.     можешь эту версию - отдельно закоммитить - для истории))
  145.     дальше развиваем)
  146. */
  147. ********************************************************************
  148.  
  149.     дореализуй еще варианты метода until
  150.  
  151.     public <V> V until(Condition<V>... conditions)
  152.     /*
  153.         суть - по очереди для каждого из кондишенов вызываем наш until(Condition<V> condition)
  154.         до тех пор, пока проверки проходят - двигаемся по набору переданных кондишенов
  155.         как только ждущая проверка для кондишена не прошла - дальше не проверяем
  156.     */
  157. ***********************
  158.  
  159. public abstract class Condition<V> {
  160.     public abstract V apply(By locator);
  161. }
  162. /*
  163.     Иерархия для кондишенов у тебя сейчас - достаточно простая
  164.  
  165.     абстрактный класс
  166.     от которого наследуются и реализуются классы-кондишены
  167.  
  168.     Минимально необходимая реализация есть
  169.  
  170.     Будем ее развивать
  171.  
  172.     Во-первых, сначала у нас будет интерфейс Condition<V>
  173.     Который будет декларировать/гарантировать
  174.  
  175.     что во всех классах, имплементирующих этот интерфейс
  176.     будут такие-то методы
  177.  
  178.     полезные линки по интерфейсам
  179.      http://kostin.ws/java/java-abstract-and-interfaces.html
  180.      http://developer.alexanderklimov.ru/android/java/interface.php
  181.      https://docs.oracle.com/javase/tutorial/java/concepts/interface.html
  182.  
  183.     теперь про методы)
  184.  
  185.     С самым главным - с apply его сигнатурой - все верно)
  186.  
  187.     В общем-то, это все, чем можно ограничиться в интерфейсе )
  188.  
  189.     Далее - абстрактный класс-предок, который мы имплементируем от интерфейса
  190.     у тебя он уже есть, надо добавить имплементацию и подправить имя - AbstractCondition<V>
  191.  
  192.     Статья про нейминг
  193.     http://www.vertigrated.com/blog/2011/02/interface-and-class-naming-anti-patterns-java-naming-convention-tautologies/
  194.  
  195.     Теперь смотрим дальше
  196.     Нам хочется, чтобы наш toString() был хорошо структурирован
  197.     Это значит, чтобы фразы были типа
  198.  
  199.           имя кондишена +
  200.           for ____element/elements___ found by: ___locator___
  201.           expected ___expected result desription_____
  202.           actual ____actual result description
  203.  
  204.     Можно конечно в каждом из кондишенов просто строить такую фразу
  205.     согласно правилу
  206.     А можно - задачу разбить на подзадачи, которые к тому же будут контролироваться
  207.     благодаря реализации этих подзадач
  208.  
  209.     Имя кондишена
  210.     Будем реализовывать кондишены как отдельные классы - потомки (пока - нашего абстрактного класса)
  211.     Откуда взять имя кондишена - у нас есть имя класса кондишена - чем не имя )
  212.  
  213.     Далее
  214.     element/elements
  215.     Это только верхушечка айсберга
  216.     Да, схема проверки кондишенов - у нас одна и та же
  217.     Хоть это кондишен для вписка элементов
  218.     Хоть для элемента
  219.     И нам нужно, чтоб наш waitUntil был один и работал с любым кондишеном
  220.  
  221.     Но
  222.     Нам важна разница - что это за кондишен - для элемента или коллекции
  223.     В данный момент - чтобы сказать про то в фразе - for ____element/elements
  224.     А далее (в следующих заданиях) - чтобы кондишены для element - мы просто  НЕ МОГЛИ применить к elements
  225.     Таким образом, приходим к тому, что у нашего общего предка AbstractCondition<V>
  226.     Будут 2 абстрактных потомка
  227.         CollectionCondition extends AbstractCondition<List<WebElement>>
  228.         ElementCondition extends AbstractCondition<WebElement>
  229.     От которых мы будем наследовать наши реальные кондишены
  230.  
  231.     И тогда, стоит держать 2 класса для реализации статических методов - вызовов кондишенов
  232.     не один, как сейчас у тебя - Conditions
  233.     а 2 =  CollectionConditions и  ElementConditions
  234.     чтобы каталоги проверок были разными для этих 2-ух типов проверок
  235.  
  236.     С иерархией разобрались немного )
  237.     Возвращаемся к фразе в toString()
  238.     Если этот метод реализовать в главном предке AbstractCondition,
  239.     и этот метод будет использовать абстрактные методы, возвращающие строки
  240.     для всех элементов этой фразы
  241.     То структура сообщения о кондишене - будет всегда четкой
  242.  
  243.     А нам останется - реализовать эти абстрактные методы, возвращающие строки
  244.     в потомках
  245.     Тут будь внимательной
  246.     Некоторые из методов надо будет реализовать уже в кондишенах-потомках
  247.     Некоторые - в CollectionCondition и ElementCondition
  248.  
  249.     Руководствуйся такими рассуждениями
  250.     Если во всех потомках я пишу одинаковый код
  251.     То лучше этот код написать в предке
  252.  
  253.     Что касается типа параметра condition для
  254.     until(Condition<V> condition)
  255.  
  256.     Ты можешь указать интерфейс Condition<V>
  257.  
  258.     И метод будет корректно работать для любого из кондишенов
  259.     Т к этот интерфейс лежит в основе этой иерархии
  260. */
  261.  
  262. *****
  263. public abstract V apply(By locator);
  264. /*
  265.     Выше я писала про то, что можно было бы внутрь apply
  266.     включить обработку исключений
  267.  
  268.     Если реализовать apply в AbstractCondition
  269.     как метод с try-catch
  270.     внутри которого вызывается абстрактный метод check (с такой же сигнатурой, как и у apply)
  271.  
  272.     то - более нигде не нужно будет ловить исключения вокруг apply
  273.     а в кондишенах - мы будем реализовыввать не apply, а check
  274. */
  275. ******
  276. /*
  277.     еще один наворот внутри кондишенов)
  278.  
  279.     мы его впоследствии переделаем
  280.  
  281.     сейчас нам это нужно для лучшего понимания процесса
  282.  
  283.     в apply передают локатор
  284.     описание которого мы возвращаем в одном из методов кондишена (для ToString)
  285.     и это - справедливо для всех кондишенов
  286.  
  287.     потому в AbstractCondition заводим переменную locator
  288.     в которую сохраняем переданный в apply локатор
  289.  
  290.     и уже в методе, возвращающем описание локатора,
  291.     оперируем этой переменной
  292.  
  293.     сразу подумай, какой модификатор доступа использовать для такой переменной
  294.     http://www.quizful.net/interview/java/access-modifiers
  295.  
  296.     но это опять была только верхушка айсберга)
  297.  
  298.     посмотри на реализованные кондишены
  299.     первой строкой в методе проверок - у тебя идет
  300.     List<WebElement> elements = getDriver().findElements(elementsLocator);
  301.     или
  302.     WebElement element = getDriver().findElement(elementsLocator);
  303.     (таких, кстати, пока нету
  304.         реализуй
  305.         visible
  306.         present
  307.         text
  308.         exactText
  309.     )
  310.  
  311.     Так вот
  312.     фактически - вот это
  313.     List<WebElement> elements = getDriver().findElements(elementsLocator);
  314.     или
  315.     WebElement element = getDriver().findElement(elementsLocator);
  316.  
  317.     это сущность типа V с точки зрения класса AbstractCondition
  318.  
  319.     давай метод check изменим
  320.     пусть принимает не локатор
  321.     а уже V entity (т е внутри кондишена в реализации check
  322.     нам ничего не придется искать по локатору - нам это уже на вход передадут)
  323.  
  324.     а вот в реализации apply в AbstractCondition
  325.     для получения этого V entity
  326.     мы объявим новый абстрактный метод getWrappedEntity()
  327.     который будет нам возвращать значение типа V
  328.  
  329.     а реализуем его в классах CollectionCondition и ElementCondition
  330.  
  331.     думаю, ты догадаешься, как )
  332.  
  333.     а вот потом, когда у нас будут наши классы для элементов (следующее задание)
  334.     мы будем в apply передавать не локатор
  335.     а сам элемент нашего нового класса
  336.     и сам элемент будет возвращать getWrappedEntity()
  337.     и мы тут, в кондишенах, избавимся от  getWrappedEntity() и его реализаций )
  338.  
  339.     пока это такой костыль
  340.     нарушающий принцип Single Responsibility
  341.     но позволяющий нам сейчас максимально реализовать код
  342.     который впоследствии изменим минимально
  343. */
Advertisement
Add Comment
Please, Sign In to add comment