Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- List<WebElement> filter(Condition<WebElement> condition);
- /*
- не)
- нам filter - все еще - как и get find ...
- вернет лейзи-сущность
- искать список вебэлементов - будем в соответствующем классе лейзи-коллекции
- а тут - мы возвращаем LazyCollection
- */
- ****************************************************
- public List<WebElement> filter(Condition<WebElement> condition) {
- return new LazyCollectionFilteredByCondition(this,condition);
- }
- /*
- реализовала верно
- но вот результат метод не такой возвращает)
- поправь объявление метода до LazyCollection filter(Condition<WebElement> condition);
- в интерфейсе и в реализации - и будет ок
- когда мы пишем - $$(...).filter(...) - мы еще ничего не ищем
- мы фиксируем - как будем искать
- а искать будем - когда будет надо )
- либо когда проверку будем выполнять
- либо - когда какие-то действия с элементом коллекции
- не раньше)
- потому - тут, на уровне вызова filter - еще нету никакой суеты с реализыми List<WebElement>
- */
- ******************************************
- public class LazyCollectionFindElement extends AbstractLazyElement {
- private LazyCollection parentCollection;
- private Condition condition;
- /*
- разумно и этот параметр объявить как Condition<WebElement>
- */
- private WebElement webElement;
- /*
- это чересчур)
- нам эта переменная нужна только внутри getWrappedEntity()
- потому - там ее и объявляй
- не надо нужное только в методе объявлять на уровне класса
- */
- ***************************
- public WebElement getWrappedEntity() {
- for (LazyElement element : parentCollection) {
- if (element.is(condition) == true) {
- webElement = element.getWrappedEntity();
- return webElement;
- }
- }
- return null;
- }
- /*
- ну да, код конечно красивый)
- можно еще и одну строчку сократить - за счет использования
- return element.getWrappedEntity();
- пока так оставим
- но тут на самом деле кроются потери времени)
- и что по факту мы делаем
- сначала - заворачиваем каждый вебэлемент списка коллекции
- (чтобы воспользоваться итератором для нашей коллекции)
- а потом - на каждом шаге - разворачиваем (получаем wrappedElement = element.getWrappedEntity())
- т е - делаем таки кучу не нужной работы
- хоть код и красивый, конечно...
- пока - оставь так)
- */
- ************************************************
- public String toString() {
- return parentCollection.toString() + " find by " + condition.toString();
- }
- /*
- использование тут condition.toString - может дать феерические глюки)
- посмотри - как устроен condition.toString
- мы там выводим имя + элемент, для которого проверку делали, ожидаемые и фактические результаты
- начнем с того, что тут тебе надо от силы - название кондишена
- а всо этого всего остального - не надо, да и не факт - что это будет корректная информация
- а кроме того - использование condition.toString - источник глюков, и не самых простых
- например, мы делаем проверку по кондишену xxx для элемента,
- полученного в том числе фильтрацией по этому же кондишену
- и проверка не проходит
- мы начинаем собирать - в тексте ошибки о не прошедшей проверке - информацию - о том, какой кондишен не прошел
- доходим до описания элемента - и снова начинаем использовать condition.toString - в котором нам нужно снова -
- описание этого же элемента
- в общем, на такие грабли тяжело наступить, но если все же наступить - можно долго разбираться)
- используй тут getClass().getSimpleName() для кондишена
- это надо и для find подправить
- */
- ****************************************
- А кроме того - скорее всего тесты будут падать)))
- нестабильно падать с Null Pointer Exception
- это - подправим на следующем шаге
- но - все равно попробуй понять - при каких обстоятельствах это происходит
- /*
- это писала в прошлый раз
- как до этого дойдешь - продолжаем )
- */
- *
- суть в чем
- например, при первом получении 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