Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- @Override
- public WebElement getWrappedEntity() {
- List<SmartElement> smartElementsList = new ArrayList<>();
- for(WebElement webElement:collection) {
- smartElementsList.add(new SmartWrappedElement(this, webElement));
- }
- /*
- collection - это SmartCollection
- и при таком обходе - ты получаешь не WebElement, а SmartElement
- вспомни - как ты итератор реализовал для коллекции
- элемент - это SmartWrappedElement, который приводится и к SmartElement
- ну и к WebElement можно привести, конечно
- только зачем)
- т е webElement - это все же уже smartElement
- нам не нужно ни дополнительно заворачивать, ни вообще - заранее обходить коллекцию
- этот же цикл можно переписать как
- for(SmartElement smartElement:smartParentCollection) {
- smartElementsList.add(smartElement);
- }
- специально изменила имена переменных - чтоб понятнее было - о чем речь
- как ты понимаешь - нету смысла такой цикл реализовывать)
- в одном вот таком цикле
- for(SmartElement smartElement:smartParentCollection)
- и будем проверять
- */
- for (SmartElement smartElement:smartElementsList) {
- if (condition.apply(smartElement) != null) {
- /*
- при работе apply - может возникнуть исключение
- посмотри - как в waitFor(..).until(...) ты вызываешь метод condition.apply
- в try-catch секции
- и тут это нужно
- если этого не сделать - можно не дойдя до нужного элемента - по исключению выйти
- можно пока - встроить тут try-catch секцию
- а можно и сразу по уму сделать
- объяви на уровне SmartElement
- метод boolean is(Condition<WebElement> condition)
- и реализуй на уровне AbstractSmartElement
- метод не должен ничего ждать
- он должен проверить - віполняется ли условие кондишена
- и там уже - тоже используй try-catch секцию
- тогда и тут код станет гораздо проще
- */
- foundElement = smartElement.getWrappedEntity();
- /*
- можно сразу return smartElement.getWrappedEntity();
- */
- }
- }
- return foundElement;
- /*
- тут просто нулл возращай
- если не нашли нужного элемента - вернем нулл
- кстати, не объявляй переменную, которая нужна только в методе
- на уровне класса
- это шанс словить феерических глюков
- на начало вызова getWrappedEntity()
- с предыдущего вызова getWrappedEntity() - в foundElement могло остаться какое-то значение
- и если в этот раз мы в цикле ничего не нашли - то вернем старое значение foundElement
- доолго можно курить и медитировать на такое )
- */
- }
- /*
- аналогично - с filter
- с именами классов - подправь по нашей схеме
- SmartFoundElement -> SmartCollectionFoundByConditionElement
- SmartCollectionInnerCollection -> SmartFilteredCollection (или полнее - SmartFilteredByConditionCollection)
- после этих преобразований - тесты иногда будут выполняться
- но чаще - падать на edit)
- чтоб не падали - читай дальше )
- */
- ***********************************
- *
- суть в чем
- например, при первом получении getWrappedEntity для
- tasks.find(cssClass("editing")).find(".edit")
- в getWrappedEntity для LazyElementInnerElement
- мы выполняем
- parentElement.getWrappedEntity().findElement(innerLocator)
- а в этот момент
- parentElement.getWrappedEntity() = null
- и мы получается у null пытаемся получить findElement(innerLocator)
- и тут происходит ошибка, которую мы не ловим
- и которую ловить - нельзя (технически - можно, но - не правильно)
- вот линка, почитай, достаточно внятная
- http://howtodoinjava.com/core-java/exception-handling/how-to-effectively-handle-nullpointerexception-in-java/
- а потом углуби понимание http://www.yegor256.com/2014/05/13/why-null-is-bad.html
- особенно внимательно на вот этот кусок посмотри http://joxi.ru/5md7jYwtvV5k8r
- получается - что good practice = обходить эти проблемы
- а не перехватывать NullPointerException
- можно конечно поступить так (это первое, что приходит в голову, НО МЫ ТАК ДЕЛАТЬ НЕ БУДЕМ)
- переписывать getWrappedEntity()
- вместо
- return parentElement.getWrappedEntity().findElement(innerLocator);
- пишем
- return parentElement.getWrappedEntity() == null ? null : parentElement.getWrappedEntity().findElement(innerLocator);
- аналогично - и в других классах
- кроме этого - поправить apply кондишена - чтобы check вызывался только если его аргумент не равен нуллу
- как ты понимаешь - это куча изменений, и достаточно легко что-то пропустить
- лучше - опереться на одно правило и его придерживаться в коде
- правило - наш код не возвращает null,
- вместо этого - вызываем исключение (напоминаю про http://joxi.ru/5md7jYwtvV5k8r)
- Дорабатываем наши кондишены
- метод check - у нас уже возвращает значение типа boolean (прошла/не прошла проверка)
- в apply -
- если проверка не прошла - вместо того, чтобы возвращать null -
- вызываем исключение WebDriverAssertionException (отнаследуй от WebDriverException)
- тут, в apply не применяем try-catch
- В WaitFor
- дорабатываем метод until
- как раз тут у нас уже есть try-catch
- получается, что если apply бросит ошибку
- то мы попадем в секцию catch ( в которой эту ошибку просто запомним - в переменную)
- (WebDriverException - мы тут ловим, значит - поймаем и WebDriverAssertionException)
- а если apply не бросит ошибку - значит все ок - проверка прошла
- потому и делаем сразу return condition.apply(lazyEntity)
- итого получили
- в реализация кондишена - мы нуллы нигде не возвращаем (или хорошее значение, или исключение)
- в реализации вейт антила - тоже самое
- причем исключения - используем разные (каждая ситуация = свое исключение)
- следующий момент
- еще один источник null - результат getWrappedEntity() для потомков AbstractLazyElement
- для коллекций такого не будет - с будет просто пустой список
- а вот с элементами - да, будет
- потому - надо чуть доработать код в getWrappedEntity() для классов семейства LazyElement
- применяем ту же логику - мы нуллы нигде не возвращаем (или хорошее значение, или исключение)
- в AbstractLazyElement реализуем getWrappedEntity()
- который вызывает абстрактный метод fetchWrappedEntity() (новый, возвращающий WebElement)
- и если результат fetchWrappedEntity() равен нулл
- то getWrappedEntity() вызовет исключение
- ElementNotFoundException (также отнаследуем от WebDriverException,
- раз у нас уже несколько своих исключений - в core создай для них свой пекедж exceptions)
- а реализация fetchWrappedEntity() - это то, что мы ранее реализовывали в getWrappedEntity()
- и тут тоже, смотри внимательно
- если мы сами пишем код (а не вызываем что-то стороннее)
- то тоже также - мы нуллы нигде не возвращаем (или хорошее значение, или исключение)
- получили и для getWrappedEntity() - нулла нам теперь этот метод не возвращает
- а это значит - не надо думать про вызовы getWrappedEntity().... - как
- про источник NullPointerExteption
- еще небольшой наворот, раз уж мы так развили работу с исключениями
- в getWrappedEntity() класса LazyCollectionNthElement
- перехватим с помощью try-catch исключение IndexOutOfBoundsException
- и вместо него бросим свое исключение
- LazyСollectionIndexOutOfBoundsException (также отнаследуем от WebDriverException)
- что это нам даст
- в WaitFor.until
- можно ловить только WebDriverException
- т е - получили более стройную логику
- а за счет того, что помимо ранее выводимой детальной информации
- о проверке, мы еще и выводим информацию об ошибке, которая привела к тому,
- что ошибка не прошла - информация о проблеме - максимально полная
- да и то, что мы нигде сами не возвращаем нуллы
- сделало наш код надежнее и проще
- теперь - тесты todoMVC падать не должны)
- */
- **********************************************
Advertisement
Add Comment
Please, Sign In to add comment