julia_v_iluhina

Untitled

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