Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-surefire-plugin</artifactId>
- <version>2.19.1</version>
- <configuration>
- <parallel>methods</parallel>
- <threadCount>5</threadCount>
- <forkCount>2</forkCount>
- <reuseForks>true</reuseForks>
- </configuration>
- </plugin>
- ...
- public class BaseTest {
- @Before
- public void init() {
- System.setProperty("webdriver.chrome.driver", "/home/belka/Chromedriver/chromedriver");
- setDriver(new ChromeDriver());
- // setDriver(new FirefoxDriver());
- }
- @After
- public void close() {
- getDriver().quit();
- }
- }
- /*
- пока предлагаю в pom - закомментировать кусок по параллельный запуск
- и в предке тест-класса - тоже перейди на BeforeClass & AfterClass
- цель - пока не тратить время при тестировании
- на создание вебдрайверов и их удаление - для каждого теста
- когда идет разработка - такие моменты пожалуй мешают
- не настаиваю, но советую)
- */
- ******************************************
- public abstract class Condition<V> {
- public abstract V apply(By locator);
- public abstract String toString();
- public static Condition<WebElement> text(final String text){
- /*
- ага, у тебя получился - такой - многофункциональный класс Condition)
- вообще - лучше придерживаться принципа Single Responsibility Principle
- погугли про это
- суть - что у каждого класса - своя ответственность
- а этот класс у нас - и абстрактный предок для кондишенов, и контейнер для реализованных кондишенов, и контейнер для логики кетчера
- будем разделять )
- по пути уже
- все без исключения классы - потомки класса Object
- а у него - реализуовн метод toString()
- соотвественно - не нужно объявлять этот метод как абстранктный
- как надумаешь реализовывать - реализуй
- а объявлять - не надо
- это уже на уровне Object сделано
- твое предложение в слеке - сделать Condition<V> - очень разумное
- ведь нам нужно для начала - лишь декларировать - что классы, имплементирующие такой интерфейс - будут реализовывать такой-то метод
- Так что - реализуй интерфейс Condition<V>
- с объявленным методом V apply(By locator)
- и это все)
- Сами кондишены - реализуй отдельныи классами, имплементирующими этот интерфейс
- Не - объектами анонимного класса
- а - именно - отдельными классами
- Позже - получим выгоды от этого
- В так реализованных классах - реализуешь
- конструктор с нудными кондишену параметрами
- собственно метод V apply(By locator)
- и toString()
- да, пока ни кетчер, ни try-catch секции в apply - применять не нужно (мы эту логику по-другому встроим)
- Пока - реализуй лишь самые необходимые кондишены
- И отдельно - реализуй класс-контейнер статических методов Conditions для вызова кондишенов
- что-то типа вот такого получишь
- public static Condition<WebElement> exactText(String expectedText) {
- return new ExactText(expectedText);
- }
- цель реализации таких методов - чтоб использовать более лаконичный вариант
- exactText(...)
- вместо
- new ExactText(...)
- и класс Conditions - будет понятным и лаконичным
- да, сущностей прибавится
- но - код станет проще и структурнее
- */
- *************************
- /*
- собственно - чтобы пощупать это новое решение в работе - мы можем использовать наш тестик google search
- нам в задании предлагалось реализовать
- assertThat(elements, nthElementText(0, “some text”));
- assertThat(element, visible());
- еще к этой паре - реализовать и size
- и как раз попробовать вариант testSearchAndFollowLink
- остальные кондишены - пока не торопись, потом реализуем, по мере необходимости
- ты уже реализовала visibilityOfElementLocated()
- как раз - вариант для нашего целевого visible()
- listNthElementHasText - тоже ок релизация
- size - в принципе тоже уже делали
- не будет чего-то особо нового
- остальные - пока просто не реализовывай даже)
- */
- *****************************
- public class Element {
- public class Elements {
- /*
- это ты убежала далеко вперед)
- это уже следующее задание
- мы пока лишь вот этот кусочек делаем
- http://joxi.ru/8An6LoZhqYgOBA
- пока - это отложи
- */
- public class Html
- /*
- пока не поняла - как это нам пригодится
- */
- *********************************************
- http://joxi.ru/zANDEYxulQ5R1m
- /*
- это тоже переноси в core
- будем внутри core - раскладывать все по подпекеджам
- уже сейчас в core создай пекедж old - будем туда складывать то, что вскоре просто удалим
- пока нам это может пригодиться - как источник некой нужной логики
- туда уже уйдет CustomConditions
- и создай пекедж entities - для Element и Elements (мы пока не будем их развивать, но позже - будем)
- и еще - пекедж conditions
- для кондишенов - интерфейса, собственно кондишенов, и класса Conditions
- */
- *****************************************
- public static <V> V waitUntil(By locator, Condition<V> condition){
- ...
- boolean conditionMatched = false;
- /*
- мы вполне можем обойтись без этой переменной
- */
- do {
- try {
- V apply = condition.apply(locator);
- if (apply != null) {
- if (conditionMatched) {
- return apply;
- } else {
- conditionMatched = true;
- sleep(Configuration.timeout);
- continue;
- }
- } else {
- conditionMatched = false;
- }
- /*
- получили результат apply
- если он не равен нулл - сразу вернули его же
- все, if-блок закончили
- а после него - просто чуть подождали sleep
- только не 4 секунды
- а миллисекунд 100 (тоже это вынеси в Configuration -
- другой переменной - pollingInterval
- чтобы тоже можно было настраивать)
- в наш общий таймаут 4 секунды мы должны многократно вызвать condition.apply
- и делать это разумно через маленькие интервальчики
- чтобы с одной стороны - лишнего не ждать (а значит - надо проверять почаще)
- а с другой стороны - не слишком частить (страница же не молниеносно загружается -
- зачем делать заведомо лишние проверки - они только ресурсы жрать будут)
- и вот такой вариант - когда общий таймаут - 4 секунды,
- а проверяем мы в рамках ждущей проверки - через каждые 100 миллисекунд
- как раз и даст нам нужный эффект
- */
- } catch (WebDriverException | InterruptedException ex) {}
- /*
- вот этот catch - и будет заменителем нашего кетчера
- в apply - не ловим исключений и не применяем кетчера в кондишенах
- а тут - будем ловить то, что ловили в кетчере
- насчет InterruptedException - есть идея - как избавиться
- */
- try {
- sleep(Configuration.timeout);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- /*
- вот этот блок - реализуй как метод sleep
- с параметром - сколько миллисекунд это делать
- и уже оперируй этим методом
- как следствие - тут не придется ловить InterruptedException
- */
- }
- while (System.currentTimeMillis() - startTime < Configuration.timeout);
- if (condition.apply(locator) == null) {
- condition.toString();
- return null;
- } else {
- return null;
- }
- /*
- тут уже можно не выполнять condition.apply
- на самом деле - мы в цикле многократно проверили наш кондишен
- и вызовем мы еше раз condition.apply или нет - большой разницы не будет
- если мы внутри цикла не вышли - значит кондишен так и не выполнился
- и значит - нам нужно вызвать исключение
- нам же нужно - чтобы тест упал
- у селениума есть подходящее исключение - TimeoutException
- в качестве сообщения - используй что-то типа
- failed while waiting ... seconds
- to assert __condition___
- __condition___ - это как раз toString кондишена
- чтобы проверить как работает ждущая проверка
- и как сообщается о возникших проблемах -
- проверяй и на заведомо не выполнимые условия
- */
- }
- ******************************
- public static WebElement $(By locator){
- /*
- этот метод - верно реализовала
- */
- public static List<WebElement> $$(By locator){
- /*
- а этот не торонись пока реализовывать
- и кондишен visibilityOfElementsLocated - тоже не торопись реализовывать
- пока закомментируй метод)
- */
- ************************************
- /*
- пока - GMail & todoMVC тесты и пейджи - тоже закомментируй
- нам уже пора проверять наше решение
- проще это делать на google search )
- пока)
- */
- *************************************
- /*
- хорошая идея - реализовать умное ожидание в отдельном классе
- с точки зрения Single Responsibility - так будет лучше
- наглядно этот класс назвать WaitFor
- а статический метод-умный ожидатель выполнения кондишена - until
- и в коде мы будем писать waitFor(byCss(...)).until(visible())
- получится очень наглядная и понятная фраза
- в том же классе - расположи и метод sleep
- а его сделай - private
- т к sleep будет нужен только для реализации ждущей проверки
- чтобы так писать - waitFor(byCss(...)).until(visible())
- реализуй конструктор с параметром By locator
- реализуй статический метод waitFor с параметром By locator
- возвращающий - новый объект класса WaitFor
- реализуй метод until(...)
- получишь
- waitFor(byCss(...)). - создали объект типа WaitFor
- until(visible()) - вызвали у него метод until
- конечно, until-у передавай как кондишен, так и таймаут
- уже второй вариант until-а - без таймаута (также как и раньше - такой берет таймаут по умолчанию)
- */
- *********************
- /*
- это еще не все, что мы сделаем в этой работе
- пока вперед не лети
- только вот это
- не торопись с элементами, коллекциями и should-ами
- это позже будет)
- */
Advertisement
Add Comment
Please, Sign In to add comment