julia_v_iluhina

Untitled

Oct 12th, 2016
91
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 13.51 KB | None | 0 0
  1.  List<WebElement> filter(Condition<WebElement> condition);
  2.  /*
  3.     не)
  4.     нам filter - все еще - как и get find ...
  5.     вернет лейзи-сущность
  6.  
  7.     искать список вебэлементов - будем в соответствующем классе лейзи-коллекции
  8.  
  9.     а тут - мы возвращаем LazyCollection
  10.  */
  11. ****************************************************
  12. public List<WebElement> filter(Condition<WebElement> condition) {
  13.         return new LazyCollectionFilteredByCondition(this,condition);
  14. }
  15. /*
  16.     реализовала верно
  17.     но вот результат метод не такой возвращает)
  18.  
  19.     поправь объявление метода до LazyCollection filter(Condition<WebElement> condition);
  20.     в интерфейсе и в реализации - и будет ок
  21.  
  22.     когда мы пишем -  $$(...).filter(...) - мы еще ничего не ищем
  23.     мы фиксируем - как будем искать
  24.  
  25.     а искать будем - когда будет надо )
  26.     либо когда проверку будем выполнять
  27.     либо - когда какие-то действия с элементом коллекции
  28.     не раньше)
  29.  
  30.     потому - тут, на уровне вызова filter - еще нету никакой суеты с реализыми List<WebElement>
  31. */
  32. ******************************************
  33.  
  34. public class LazyCollectionFindElement extends AbstractLazyElement {
  35.  
  36.     private LazyCollection parentCollection;
  37.     private Condition condition;
  38.     /*
  39.         разумно и этот параметр объявить как Condition<WebElement>
  40.     */
  41.     private WebElement webElement;
  42.     /*
  43.         это чересчур)
  44.         нам эта переменная нужна только внутри getWrappedEntity()
  45.         потому - там ее и объявляй
  46.         не надо нужное только в методе объявлять на уровне класса
  47.     */
  48.  
  49.   ***************************
  50.  
  51.     public WebElement getWrappedEntity() {
  52.         for (LazyElement element : parentCollection) {
  53.             if (element.is(condition) == true) {
  54.                 webElement = element.getWrappedEntity();
  55.                 return webElement;
  56.             }
  57.         }
  58.         return null;
  59.     }
  60.   /*
  61.     ну да, код конечно красивый)
  62.     можно еще и одну строчку сократить - за счет использования
  63.     return element.getWrappedEntity();
  64.  
  65.     пока так оставим
  66.     но тут на самом деле кроются потери времени)
  67.  
  68.         и что по факту мы делаем
  69.  
  70.                 сначала - заворачиваем каждый вебэлемент списка коллекции
  71.                 (чтобы воспользоваться итератором для нашей коллекции)
  72.                 а потом - на каждом шаге - разворачиваем (получаем wrappedElement = element.getWrappedEntity())
  73.  
  74.                 т е - делаем таки кучу не нужной работы
  75.                 хоть код и красивый, конечно...
  76.     пока - оставь так)
  77.   */
  78. ************************************************
  79.     public String toString() {
  80.         return parentCollection.toString() + " find by " + condition.toString();
  81.     }
  82. /*
  83.     использование тут condition.toString - может дать феерические глюки)
  84.  
  85.     посмотри - как устроен condition.toString
  86.     мы там выводим имя + элемент, для которого проверку делали, ожидаемые и фактические результаты
  87.  
  88.     начнем с того, что тут тебе надо от силы - название кондишена
  89.     а всо этого всего остального - не надо, да и не факт  - что это будет корректная информация
  90.  
  91.     а кроме того - использование condition.toString - источник глюков, и не самых простых
  92.     например, мы делаем проверку по кондишену xxx для элемента,
  93.     полученного в том числе фильтрацией по этому же кондишену
  94.     и проверка не проходит
  95.     мы начинаем собирать - в тексте ошибки о не прошедшей проверке - информацию - о том, какой кондишен не прошел
  96.     доходим до описания элемента - и снова начинаем использовать condition.toString - в котором нам нужно снова -
  97.     описание этого же элемента
  98.  
  99.     в общем, на такие грабли тяжело наступить, но если все же наступить - можно долго разбираться)
  100.  
  101.     используй тут getClass().getSimpleName() для кондишена
  102.  
  103.     это надо и для find подправить
  104. */
  105. ****************************************
  106. А кроме того - скорее всего тесты будут падать)))
  107. нестабильно падать с Null Pointer Exception
  108. это - подправим на следующем шаге
  109.  
  110. но  - все равно попробуй понять - при каких обстоятельствах это происходит
  111. /*
  112.     это писала в прошлый раз
  113.  
  114.     как до этого дойдешь - продолжаем )
  115. */
  116. *
  117.   суть в чем
  118.     например, при первом получении getWrappedEntity для
  119.         tasks.find(cssClass("editing")).find(".edit")
  120.  
  121.     в getWrappedEntity для LazyElementInnerElement
  122.     мы выполняем
  123.     parentElement.getWrappedEntity().findElement(innerLocator)
  124.  
  125.     а в этот момент
  126.     parentElement.getWrappedEntity() = null
  127.  
  128.     и мы получается у null пытаемся получить findElement(innerLocator)
  129.  
  130.     и тут происходит ошибка, которую мы не ловим
  131.     и которую ловить - нельзя (технически - можно, но - не правильно)
  132.  
  133.     вот линка, почитай, достаточно внятная
  134.     http://howtodoinjava.com/core-java/exception-handling/how-to-effectively-handle-nullpointerexception-in-java/
  135.  
  136.     а потом углуби понимание http://www.yegor256.com/2014/05/13/why-null-is-bad.html
  137.     особенно внимательно на вот этот кусок посмотри http://joxi.ru/5md7jYwtvV5k8r
  138.  
  139.     получается - что good practice = обходить эти проблемы
  140.     а не перехватывать NullPointerException
  141.  
  142.     можно конечно поступить так (это первое, что приходит в голову, НО МЫ ТАК ДЕЛАТЬ НЕ БУДЕМ)
  143.  
  144.         переписывать getWrappedEntity()
  145.             вместо
  146.             return parentElement.getWrappedEntity().findElement(innerLocator);
  147.             пишем
  148.             return parentElement.getWrappedEntity() == null ? null : parentElement.getWrappedEntity().findElement(innerLocator);
  149.  
  150.         аналогично - и в других классах
  151.  
  152.         кроме этого - поправить apply кондишена - чтобы check вызывался только если его аргумент не равен нуллу
  153.  
  154.     как ты понимаешь - это куча изменений, и достаточно легко что-то пропустить
  155.     лучше - опереться на одно правило и его придерживаться в коде
  156.  
  157.     правило - наш код не возвращает null,
  158.     вместо этого - вызываем исключение (напоминаю про http://joxi.ru/5md7jYwtvV5k8r)
  159.  
  160.     Дорабатываем наши кондишены
  161.         метод check - у нас уже возвращает значение типа boolean (прошла/не прошла проверка)
  162.         в apply -
  163.             если проверка не прошла - вместо того, чтобы возвращать null -
  164.             вызываем исключение WebDriverAssertionException (отнаследуй от WebDriverException)
  165.  
  166.             тут, в apply не применяем try-catch
  167.  
  168.     В WaitFor
  169.         дорабатываем метод until
  170.             как раз тут у нас уже есть try-catch
  171.  
  172.             получается, что если apply бросит ошибку
  173.             то мы попадем в секцию catch ( в которой эту ошибку просто запомним - в переменную)
  174.             (WebDriverException - мы тут ловим, значит - поймаем и WebDriverAssertionException)
  175.  
  176.             а если apply не бросит ошибку - значит все ок - проверка прошла
  177.             потому и делаем сразу return condition.apply(lazyEntity)
  178.  
  179.             итого получили
  180.               в реализация кондишена - мы нуллы нигде не возвращаем (или хорошее значение, или исключение)
  181.               в реализации вейт антила - тоже самое
  182.               причем исключения - используем разные (каждая ситуация = свое исключение)
  183.  
  184.            следующий момент
  185.              еще один источник null - результат getWrappedEntity() для потомков AbstractLazyElement
  186.              для коллекций такого не будет - с будет просто пустой список
  187.              а вот с элементами - да, будет
  188.              потому - надо чуть доработать код в getWrappedEntity() для классов семейства LazyElement
  189.  
  190.              применяем ту же логику - мы нуллы нигде не возвращаем (или хорошее значение, или исключение)
  191.                 в AbstractLazyElement реализуем getWrappedEntity()
  192.                 который вызывает абстрактный метод fetchWrappedEntity() (новый, возвращающий WebElement)
  193.                 и если результат fetchWrappedEntity() равен нулл
  194.                 то getWrappedEntity() вызовет исключение
  195.                 ElementNotFoundException (также отнаследуем от WebDriverException,
  196.                 раз у нас уже несколько своих исключений - в core создай для них свой пекедж exceptions)
  197.  
  198.                 а реализация fetchWrappedEntity() - это то, что мы ранее реализовывали в getWrappedEntity()
  199.  
  200.                 и тут тоже, смотри внимательно
  201.                 если мы сами пишем код (а не вызываем что-то стороннее)
  202.                 то тоже также - мы нуллы нигде не возвращаем (или хорошее значение, или исключение)
  203.  
  204.              получили и для getWrappedEntity() - нулла нам теперь этот метод не возвращает
  205.              а это значит - не надо думать про вызовы getWrappedEntity().... - как
  206.              про источник NullPointerExteption
  207.  
  208.           еще небольшой наворот, раз уж мы так развили работу с исключениями
  209.             в getWrappedEntity() класса LazyCollectionNthElement
  210.             перехватим с помощью try-catch исключение IndexOutOfBoundsException
  211.             и вместо него бросим свое исключение
  212.             LazyСollectionIndexOutOfBoundsException (также отнаследуем от WebDriverException)
  213.  
  214.             что это нам даст
  215.             в WaitFor.until
  216.             можно ловить только WebDriverException
  217.  
  218.             т е  - получили более стройную логику
  219.  
  220.           а за счет того, что помимо ранее выводимой детальной информации
  221.           о проверке, мы еще и выводим информацию об ошибке, которая привела к тому,
  222.           что ошибка не прошла - информация о проблеме - максимально полная
  223.  
  224.           да и то, что мы нигде сами не возвращаем нуллы
  225.           сделало наш код надежнее и проще
  226.  
  227.           теперь - тесты todoMVC падать не должны)
  228. */
  229. **********************************************
Advertisement
Add Comment
Please, Sign In to add comment