julia_v_iluhina

Untitled

Oct 13th, 2016
95
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 17.98 KB | None | 0 0
  1. *******************************
  2. if (element.is(condition) == true)
  3.  
  4. /*
  5.     такой код равносилен
  6.     if (element.is(condition))
  7.  
  8.     мной приведенный вариант красивее)
  9.     меньше действий )
  10.     да/нет с да не сравниваем
  11.     сразу оперируем да/нет - которое уже получили
  12. */
  13. **********************************
  14.   public WebElement getWrappedEntity() {
  15.         if (fetchWrappedEntity() == null) {
  16.             throw new ElementNotFoundException();
  17.         }
  18.         return fetchWrappedEntity();
  19.     }
  20. /*
  21.     не надо дважды получать fetchWrappedEntity()
  22.     один раз получили, сохранили в переменную
  23.  
  24.     и если все ок - ее же и вернули
  25.  
  26.     что касается исключения - хорошо бы в конструктор исключения слова какие-то передать
  27.     что же за элемент му не нашли
  28.     лучше чем вариант с toString этого же объекта(лейзи-элемента) - у нас нету
  29.  
  30.     для этого придется реализовать конструктор для ElementNotFoundException
  31.     с одним параметром String message
  32.     в котором вызови аналогичный конструктор предка
  33.         http://developer.alexanderklimov.ru/android/java/extends.php
  34.         http://metanit.com/java/tutorial/3.5.php
  35.         https://docs.oracle.com/javase/tutorial/java/IandI/super.html
  36.  
  37. */
  38.  
  39. ***************************************
  40. public class LazyCollectionFindElement extends AbstractLazyElement {
  41.  
  42. ...
  43.     @Override
  44.     public WebElement fetchWrappedEntity() {
  45.         ...
  46.         return null;
  47.     }
  48.     /*
  49.         мы своими руками - null не возвращаем
  50.         сразу бросаем исключение - не нашли элемента
  51.         ElementNotFoundException - и тут подойдет
  52.  
  53.         то же самое - в конструктор исклюсения передавай toString
  54.  
  55.         да, можно возразить - что на следующем шаге мі и так проверим на нулл и бросим исключение
  56.  
  57.         Будем последовательны) сами никаких нуллов не вернем нигде
  58.         так проще - меньше помнить придется - что где и как реализовано
  59.     */
  60. **********************************
  61.     public class LazyCollectionFindElement extends AbstractLazyElement {
  62. /*
  63.     корректнее назвать такой класс LazyCollectionFoundByConditionElement
  64.     ну или LazyCollectionFoundElement
  65. */
  66. ***********************************
  67. public class LazyCollectionNthElement extends AbstractLazyElement {
  68.  
  69. ....
  70.     public WebElement fetchWrappedEntity() {
  71.         WebElement element = null;
  72.         try {
  73.             element = parentCollection.getWrappedEntity().get(index);
  74.             if (element != null) {
  75.                 return element;
  76.             }
  77.             /*
  78.                 я не это имела в виду в прошлом ревью
  79.  
  80.                 тут - внутри try-catch
  81.                 просто возвращай parentCollection.getWrappedEntity().get(index);
  82.  
  83.                 дополнительного сравнения на нулл не надо
  84.                 мы явно - нулл не возвращаем (тут же мы нигде не написали - return null)
  85.                 а сравнение на нулл - есть в getWrappedEntity
  86.                 не надо лишнего кода
  87.  
  88.                 наша цель - не писать вот так - return null
  89.                 и в ключевых местах - встроить проверки на нулл
  90.                 но только там
  91.                 собственно, использование вот такой схемы - вместо возврата нуллов кидать исключения
  92.                 как раз и нужно - чтоб избежать кучи  if (... != null)
  93.                 в различных частях кода
  94.             */
  95.         } catch (LazyСollectionIndexOutOfBoundsException e) {
  96.         /*
  97.             тут - лови IndexOutOfBoundsException - т к именно такое исключение может возникнуть
  98.             если в get(index) - индекс выходит за границы коллекции
  99.             и если словится - вместо такого исключения - кидай LazyСollectionIndexOutOfBoundsException
  100.  
  101.             кстати - обрати внимание - LazyСolleсtionIndexOutOfBoundsException - подчеркивается кусок имени
  102.             зеленой волнистой линией, где-то русские буквы есть )
  103.  
  104.             цель - свести все исключения к потомкам WebDriverException
  105.         */
  106.         }
  107.         return element;
  108.         /*
  109.             как ты понимаешь - нам не понадобится ни этой строки
  110.             ни переменной element
  111.         */
  112.     }
  113. *************************************
  114. public class LazyWebDriverElement extends AbstractLazyElement {
  115.  
  116.     public LazyWebDriverElement(AbstractLazyElement abstractLazyElement, By innerLocator) {
  117.         super();
  118.     }
  119. /*
  120.     вот это не ясно для чего )
  121.     для чего?
  122. */
  123. ***************************************
  124. public class LazyCollectionFilteredByCondition extends AbstractLazyCollection
  125. /*
  126.     т к фильтровать можно лишь коллекции
  127.     тут можно сэкономить на имени класса
  128.     LazyFilteredCollection
  129.     LazyFilteredByConditionCollection
  130.  
  131.     а если не экономить - то по нашей схеме
  132.     LazyCollectionFilteredByConditionCollection
  133. */
  134. ******************************************
  135.  public V apply(LazyEntity<V> entity) {
  136.         ...
  137.         if (check(wrappedEntity)== true) {
  138.         /*
  139.             достаточно if (check(wrappedEntity))
  140.         */
  141.         throw new WebDriverAssertionException();
  142.         /*
  143.             тут тоже в конструктор исключения - передавай toString самого кондишена
  144.             и для этого исключения придется реализовать конструктор с параметром String message
  145.         */
  146.  
  147.  }
  148. *************************************
  149.   public T until(Condition <T> condition, long timeout) {
  150.          Throwable lastError = null;
  151.          long startTime = System.currentTimeMillis();
  152.  
  153.          do {
  154.              try {
  155.                  T result = condition.apply(entity);
  156.                  if (result != null) {
  157.                      return result;
  158.                  }
  159.                  /*
  160.                     и тут код упростится
  161.                     apply нам не вернет null
  162.  
  163.                     он или что-то хорошее вернет
  164.                     или бросит WebDriverAssertionException
  165.  
  166.                     потому можно сразу писать
  167.                     return condition.apply(entity);
  168.                  */
  169.              } catch (WebDriverException | IndexOutOfBoundsException e) {
  170.              /*
  171.                 а тут - уже не надо ловить IndexOutOfBoundsException
  172.                 мы еще на этапе fetchWrappedEntity() в LazyCollectionNthElement это решили
  173.                 теперь нас интересуют только потомки WebDriverException
  174.              */
  175.                  lastError = e;
  176.              }
  177.  
  178.              sleep(Configuration.pollingInterval);
  179.          } while (System.currentTimeMillis() - startTime < timeout);
  180.          throw new TimeoutException(String.format("failed while waiting %d milliseconds to assert %s", timeout, condition.toString()), lastError);
  181.   }
  182.  ******************************************
  183.   public boolean is(Condition<WebElement> condition) {
  184.           try {
  185.               WebElement result = condition.apply(this);
  186.               if (result != null) {
  187.                   return true;
  188.               }
  189.               /*
  190.                 и тут упрощай
  191.                 просто -
  192.                 condition.apply(this);
  193.                 return true;
  194.                 если будет выполняться следующая строка после condition.apply(this);
  195.                 значит - исключения не возникло
  196.                 и значение condition.apply(this) - не равно нуллу
  197.               */
  198.           } catch (WebDriverException | IndexOutOfBoundsException e) {
  199.           /*
  200.             тут тоже лови только WebDriverException
  201.           */
  202.               return false;
  203.               /*
  204.                 этого можешь не писать
  205.               */
  206.           }
  207.           return false;
  208.           /*
  209.             потому что есть эта строка
  210.           */
  211.       }
  212. ******************************
  213. public class BaseTest {
  214.  
  215.     @Before
  216.     public void setUp() {
  217.         setDriver(new FirefoxDriver());
  218.     }
  219.  
  220.     @After
  221.     public void tearDown() {
  222.         getDriver().quit();
  223.     }
  224. }
  225. /*
  226.     если сейчас е используешь параллельный запуск - так тогда разумнее
  227.     в BeforeClass & AfterClass создавать и закрывать вебдрайвер
  228.  
  229.     обрати внимание - таймаут ты в потомках настраивала в BeforeClass методе
  230.  
  231.     тут желательно все соответственно делать
  232. */
  233. *********************************************
  234. @Override
  235.     public LazyElement doubleClick() {
  236.         waitFor(this).until(visible());
  237.         actions().doubleClick(this).perform();
  238.         return this;
  239.     }
  240.  
  241.     @Override
  242.     public LazyElement hover() {
  243.         waitFor(this).until(visible());
  244.         actions().moveToElement(this).perform();
  245.         return this;
  246.     }
  247. /*
  248.     а чего в этих методах
  249.         actions().moveToElement(this).perform();
  250.         а не
  251.         actions().moveToElement(getWrappedEntity()).perform();
  252.  
  253.     ?
  254.  
  255.     нам нужно оперировать уже вебэлементом
  256.     когда дело доходит до конкретного действия
  257. */
  258. ****************************************
  259. public class CssClass extends AbstractCondition<WebElement> {
  260.  
  261. ...
  262.     @Override
  263.     public boolean check(WebElement element) {
  264.         attribute = element.getAttribute("class");
  265.         return (attribute.equals(cssClass));
  266.     }
  267. /*
  268.     еще одна ошибка нашлась
  269.  
  270.     вспомни прошлые работы - как был реализован кондишен - работающий с классами
  271.  
  272.     мы получали значение атрибута class
  273.     там содержатся классы, перечисленные через пробел
  274.     мы эту строку разбивали на слова
  275.     и если один из классов равен оюидаемому - да
  276.     проверка прошла
  277.  
  278.     просто сравнивать на равенство - не получится
  279.     у элемента может быть несколько классов
  280.  
  281.     вот тут - уже все тест-методы должны работать)
  282.     если так - идем дальше
  283. */
  284. ********************************************************
  285.  
  286.     @Override
  287.     public WebElement fetchWrappedEntity() {
  288.         for (LazyElement element : parentCollection) {
  289.             if (element.is(condition)) {
  290.                 return element.getWrappedEntity();
  291.             }
  292.         }
  293.         throw new ElementNotFoundException(toString());
  294.     }
  295. /*
  296.     ну да, код конечно красивый)
  297.  
  298.     и что по факту мы делаем
  299.  
  300.             сначала - заворачиваем каждый вебэлемент списка коллекции
  301.             (чтобы воспользоваться итератором для нашей коллекции)
  302.             а потом - на каждом шаге - разворачиваем (получаем wrappedElement = element.getWrappedEntity())
  303.  
  304.             т е - делаем таки кучу не нужной работы
  305.             хоть код и красивый, конечно...
  306.  
  307.         правильнее - для оптимизации реально выполняемых действий -
  308.         отказаться от идеи обхода коллекции таким образом
  309.             for (LazyElement element : parentCollection)
  310.  
  311.         а реализовать вот так
  312.             получить список вебэлементов parentCollection.getWrappedEntity()
  313.             обойти полученный список вебэлементов в цикле
  314.             и применять к вебэлементу - метод check
  315.             правда, для этого объявление метода check придется вынести на уровень интерфейса Condition
  316.  
  317.             сэкономим на заворачиваниях-разворачиваниях)
  318.  
  319.   */
  320. *********************************
  321. public interface Condition<T> {
  322.     T apply(LazyEntity<T> entity);
  323.  
  324.     boolean check(T wrappedEntity);
  325. }
  326.  
  327. /*
  328.     делаем красиво)
  329.  
  330.     сейчас в этом интерфейсе - объявлены методы
  331.         служащие как для принятия решения - прошли-не прошли
  332.         так и для получения результата ожидания
  333.  
  334.     нарушаем Single Responsibility Principle )
  335.  
  336.     реализуй интерфейс Matcher <T> с объявленным методом boolean check(T wrappedEntity);
  337.  
  338.     а в Condition <T> - останется apply
  339.     Condition <T> - отнаследуй от Matcher <T>
  340. */
  341. ************************************
  342.  /*
  343.     а теперь и метод is можно реализовать чуть красивее - с использованием check кондишена
  344.  */
  345. ********************************************
  346. /*
  347.     еще немного challenge )
  348.  
  349.     в интерфейсе LazyElement
  350.         объяви методы
  351.     LazyCollection findAll(By innerLocator);
  352.     LazyCollection findAll(String innerCssSelector);
  353.  
  354.     и реализуй их в AbstractLazyElement
  355.  
  356.     этот метод позволит у элемента  - по селектору или локатору - получить коллекцию внутренних элементов
  357.  
  358.     отладиться можно - используя
  359.     LazyCollection tasks = $("#todo-list").findAll("li");
  360.     или
  361.     LazyCollectionLazyCollection emails = $("[role='main']").findAll(".zA");
  362.  
  363.     Иногда такой метод findAll будет очень полезным
  364.  
  365.     принципы - те же
  366.     как ты до этого реализовывала методы get, find, filter ...
  367.  
  368.     так сказать - для закрепления результатов)
  369. */
  370. ********************************************
  371. /*
  372.     насчет использования модификатора доступа protected
  373.  
  374.         есть такая точка зрения, что использовать protected - это самообман
  375.         т к в рамках потомков можно для отнаследованного protected-метода
  376.         этот метод сделать публичным
  377.  
  378.         когда мы использовали protected, мы хотели, чтобы что-то было с возможностью наследования
  379.         и не хотели его внешнего использования.
  380.         а кто-то отнаследовался от нашего класса и объявил это как public
  381.         и вот то, что мы прятали внутри класса - уже "торчит" наружу
  382.  
  383.         есть good practice - избегать применения protected
  384.         то, что мы что-то объявим внутри класса-кондишена как public
  385.         не будет нам особо мешать при работе с нашим фреймворком
  386.         т к в итоге - используем для кондишена тип интерфейс,
  387.         и это позволит не светить нашими публичными переменными/методами
  388.         когда будем юзать фреймворк
  389.  
  390.         идеально про протектед-методы
  391.             http://programmers.stackexchange.com/questions/162643/why-is-clean-code-suggesting-avoiding-protected-variables
  392.             http://joxi.ru/52akqzoUGnqYGr
  393.  
  394.             http://stackoverflow.com/questions/3631176/why-are-many-developers-opposed-to-using-the-protected-modifier-in-oop
  395.             http://stackoverflow.com/questions/37011/should-you-ever-use-protected-member-variables
  396.             http://stackoverflow.com/questions/4913025/reasons-to-use-private-instead-of-protected-for-fields-and-methods
  397.  
  398.             http://www.javalobby.org/java/forums/t77911.html
  399.  
  400.     Просмотри весь проект, перейди на использование public
  401. */
Advertisement
Add Comment
Please, Sign In to add comment