julia_v_iluhina

Untitled

Nov 24th, 2016
83
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 12.62 KB | None | 0 0
  1. http://joxi.ru/E2pdR1lFBdXng2
  2.  
  3. /*
  4.     лишнее есть в репозитории
  5.     скорей всего добавил - перед созданием .gitignore
  6.  
  7.  
  8.     https://help.github.com/articles/removing-a-remote/
  9.     http://stackoverflow.com/questions/7927230/remove-directory-from-remote-repository-after-adding-them-to-gitignore
  10.     http://stackoverflow.com/questions/13541615/how-to-remove-files-that-are-listed-in-the-gitignore-but-still-on-the-repositor
  11.  
  12.     https://git-scm.com/docs/git-rm
  13. */
  14. ***********************
  15. *****************************
  16. public abstract class OwnCondition<T> {
  17.  
  18.     public abstract T apply(By locator);
  19.  
  20. }
  21. ...
  22. public class CustomConditions {
  23.     public static OwnCondition<WebElement> nthElementHasText(final int index, final String text) {
  24.     ....
  25.     public static <V> OwnCondition<V> elementExceptionsCatcher(final OwnCondition<V> condition) {
  26. /*
  27.     давай для начала - чуть упростим)
  28.     избавимся от кетчера
  29.     то, что мы ловили с кетчере - мы спокойно можем ловить и в ConciseAPI#waitUntil
  30.     завернем apply в try-catch - и можно убирать кетчера
  31.  
  32.     далее
  33.     реализуем кондишены не как не объекты анонимного класса
  34.     а так
  35.         отдельно - классы-кондишены
  36.         а в CustomConditions - методы будут создавать объекты вот тех, отдельно реализованных классов-кондишенов
  37.         прибавится порядка в CustomConditions - кода станет меньше и и он будет проще
  38.  
  39.         будут еще положительные моменты от этого
  40.         но это мы сможем оценить чуть позже в полном объеме)
  41.  
  42.     еще - посмотри на наш абстрактный класс OwnCondition
  43.     раз мы на его уровне ничего не реализуем - мы можем объявить его как интерфейс
  44.     и далее - уже классы-кондишены имплементировать от этого интерфейса
  45.  
  46.     собственно - для этого интерфейсы и объявляют
  47.     чтобы разные классы, которые имплементируют интерфейс -
  48.     оперировали одними и теми же методами
  49.     и мы могли, объявив переменную типа интерфейс - работать с объектом любого из таких классов
  50.  
  51.      полезные линки по интерфейсам
  52.          http://kostin.ws/java/java-abstract-and-interfaces.html
  53.  
  54.          http://developer.alexanderklimov.ru/android/java/interface.php
  55.  
  56.          https://docs.oracle.com/javase/tutorial/java/concepts/interface.html
  57.  
  58.  
  59.     Статья про нейминг - интерфейсы + классы
  60.     http://www.vertigrated.com/blog/2011/02/interface-and-class-naming-anti-patterns-java-naming-convention-tautologies/
  61.  
  62.  
  63.     http://stackoverflow.com/questions/1932247/abstract-classes-and-interfaces-best-practices-in-java
  64.     http://joxi.ru/E2pdR1lFB1pyM2
  65.  
  66.     Будет ОК - назвать интерфейс Condition
  67.     В Selenium такое имя не используется, так что ок будет
  68. */
  69. public  class ConciseAPI {
  70.     ...
  71.  
  72.     public static <V> V waitUntil(By locator, OwnCondition<V> condition, long timeout) {
  73.         long endTime = System.currentTimeMillis() + timeout;
  74.  
  75.         for( ;endTime > System.currentTimeMillis(); ) {
  76.         /*
  77.             while - тут был бы нагляднее
  78.             http://developer.alexanderklimov.ru/android/java/while.php
  79.         */
  80.             V result = condition.apply(locator);
  81.             if (result != null) {
  82.                 return result;
  83.             }
  84.             try {
  85.                 sleep(100);
  86.             } catch (InterruptedException e) {
  87.                 e.printStackTrace();
  88.             }
  89.             /*
  90.                 вот эту try-catch секцию - реализуй как отдельный метод sleep
  91.                 и тут вызывай
  92.                 вот эта цифра - 100 миллисекунд - это тоже лучше настраивать
  93.                 вынеси в Configuration - и эту переменную
  94.             */
  95.         }
  96.         return null;
  97.         /*
  98.             если мы прождали-пропроверяли в течение всего таймаута
  99.             и проверка не прошла - нам не нулл нужно вернуть
  100.  
  101.             нам нужно обеспечить - чтоб тест упал
  102.  
  103.             разумно использовать исключение селениумское - TimeOutException
  104.             его нужно вызвать и в качестве параметра конструктора - передать сообщение об ошибке
  105.             именно это сообщение мы и увидим - когда тест упадет на проверке
  106.             вот такое сообщение - будет достаточно информативным
  107.             failed while waiting ... seconds
  108.             to assert ...(описание кондишена)
  109.  
  110.             http://howtodoinjava.com/best-practices/java-exception-handling-best-practices/
  111.             http://www.developer.com/java/data/best-practices-in-java-exception-handling.html
  112.             https://www.javacodegeeks.com/2013/07/java-exception-handling-tutorial-with-examples-and-best-practices.html
  113.  
  114.  
  115.             https://habrahabr.ru/company/golovachcourses/blog/225585/
  116.            
  117.            
  118.             проверяй работу waituntil и кондишенов - на двух вариантах кода
  119.             когда проверка должна пройти
  120.             когда она не должна пройти
  121.             и плюс к этому - когда проверка не должна пройти - смотри на сообщение об ошибке
  122.         */
  123.     }
  124. ************************************************************
  125.     /*
  126.         Иерархия для кондишенов у тебя сейчас - достаточно простая
  127.    
  128.         интерфейс
  129.         и классы-кондишены, имплементирующие его
  130.    
  131.         Минимально необходимая реализация есть
  132.    
  133.         Будем ее развивать
  134.    
  135.         Далее - реализуй абстрактный класс-предок AbstractCondition<V> ,
  136.         который имплементирует интерфейс Condition<V>
  137.    
  138.         Статья про нейминг
  139.         http://www.vertigrated.com/blog/2011/02/interface-and-class-naming-anti-patterns-java-naming-convention-tautologies/
  140.    
  141.         Теперь смотрим дальше
  142.         Нам хочется, чтобы наш toString() для любого кондишена был хорошо структурирован
  143.         Это значит, чтобы фразы были типа
  144.    
  145.               __имя кондишена__ +
  146.               for ____element/elements___ found by: ___locator___
  147.               expected ___expected result description_____
  148.               actual ____actual result description_____
  149.    
  150.         Можно конечно в каждом из кондишенов просто строить такую фразу
  151.         согласно правилу
  152.    
  153.         А можно - toString() реализовать в абстрактном классе, и внутри этого метода - вызывать абстрактные методы
  154.         а их уже - реализуем в потомках. Таким образом - структура сообщения любого из кондишенов
  155.         будет одинаковой
  156.    
  157.         где брать ___locator___ тут - мы чуть позже поговорим...
  158.         пока пропусти этот момент
  159.    
  160.         а вто для
  161.             ____element/elements___
  162.             ___expected result description_____
  163.             ____actual result description____
  164.         объяви и используй абстрактные методы
  165.             identity()
  166.             expected()
  167.             actual()
  168.    
  169.         __имя кондишена__
  170.         раз мы будем реализовывать кондишены как отдельные классы - потомки (пока - нашего абстрактного класса)
  171.         то откуда взять имя кондишена - у нас есть
  172.         у нас есть имя класса кондишена - чем не имя )
  173.    
  174.         Далее
  175.         element/elements
  176.         Это только верхушечка айсберга
  177.         Да, схема проверки кондишенов - у нас одна и та же
  178.         Хоть это кондишен для списка элементов
  179.         Хоть для элемента
  180.         И нам нужно, чтоб наш waitUntil был один и работал с любым кондишеном
  181.    
  182.         Но
  183.         Нам важна разница - что это за кондишен - для элемента или коллекции
  184.         В данный момент - чтобы сказать про то в фразе - for ____element/elements
  185.         А далее (в следующих заданиях) - чтобы кондишены для element - мы просто  НЕ МОГЛИ применить к elements
  186.         Таким образом, приходим к тому, что у нашего общего предка AbstractCondition<V>
  187.         Будут 2 абстрактных потомка
  188.             CollectionCondition extends AbstractCondition<List<WebElement>>
  189.             ElementCondition extends AbstractCondition<WebElement>
  190.         От которых мы будем наследовать наши реальные кондишены
  191.    
  192.         И тогда, стоит держать 2 класса для реализации статических методов - вызовов кондишенов
  193.         CollectionConditions и  ElementConditions
  194.             это будут классы-контейнеры статических методов
  195.             типа
  196.             public static Condition<WebElement> visible() {
  197.                 return new Visible();
  198.             }
  199.             чтобы уже в коде  - не писать - new Visible()
  200.    
  201.         С иерархией разобрались немного )
  202.    
  203.         Возвращаемся к фразе в toString()
  204.             Если этот метод реализовать в главном предке AbstractCondition,
  205.             и этот метод будет использовать абстрактные методы, возвращающие строки
  206.             для всех элементов этой фразы
  207.             То структура сообщения о кондишене - будет всегда четкой
  208.    
  209.         А нам останется - реализовать эти абстрактные методы, возвращающие строки
  210.         в потомках
  211.         Тут смотри внимательно
  212.         Некоторые из методов надо будет реализовать уже в кондишенах-потомках
  213.         Некоторые - в CollectionCondition и ElementCondition
  214.    
  215.         Руководствуйся такими рассуждениями
  216.         Если во всех потомках я пишу одинаковый код
  217.         То лучше этот код написать в предке
  218.    
  219.         Что касается типа параметра condition для
  220.         until(Condition<V> condition)
  221.    
  222.         Ты можешь указать интерфейс Condition<V>
  223.    
  224.         И метод будет корректно работать для любого из кондишенов
  225.         Т к этот интерфейс лежит в основе этой иерархии
  226.     */
Advertisement
Add Comment
Please, Sign In to add comment