Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- public class Configuration {
- public static int timeout = 35;
- }
- /*
- тут - утанавливаем значение по умолчанию
- это - такое значение, которое подходит для большинства
- в селениде - это было 4 секунды
- предлагаю и нам тут именно 4 секунды прописать
- а уже в тест-классе - укажешь 35 секунд
- вспомни - как мы это делали в селенидовском решении
- тут - аналогично
- */
- ************************************
- public static ExpectedCondition<Boolean> nthElementHasText(final List<WebElement> elements , final int index, final String text) {
- /*
- реализовывать этот кондишен как ExpectedCondition<Boolean> - пользы мало
- я бы реализовала его как
- ExpectedCondition<WebElement> - тогда apply возвращал бы в случае успеха вебэлемент с нужным текстом
- (или null - в случае не успеха)
- или
- ExpectedCondition<List<WebElement>> - тогда apply возвращал бы в случае успеха список веб элементов
- (тот же, что пришел на вход)
- в таком случае можно было бы воспользоваться результатом, который вернет assertThat для єтого кондишена
- */
- return new ExpectedCondition<Boolean>() {
- private List<WebElement> copyElements = elements;
- /*
- хитро придумал)
- только надо доработать эту идею
- во-первых - ты пока завел переменную, которая не новый список-копия
- а которая указвает на тот же лейзи прокси список
- т е - ты не ушел от того - что список лейзи прокси
- как копировать списки
- http://stackoverflow.com/questions/689370/java-collections-copy-list-i-dont-understand
- http://stackoverflow.com/questions/14319732/how-to-copy-a-java-util-list-into-another-java-util-list
- еще момент
- мы скопируем ЕДИНОЖДЫ этот список = завиксируем состояние
- и потом многократно вызовем apply
- в котором будем проверять не истинное положение дел
- а вот то,первое зафиксированное состояние
- вывод - вот такая операция - должна происходить не при инициализации кондишена
- а в начале выполнения apply
- и все же больше пользы было бы именно в списке текстов
- а не списке элементов
- хотя и мысль красивая)
- ниже поясню
- */
- public Boolean apply(WebDriver driver) {
- if (!copyElements.get(index).getText().contains(text)){
- return false;
- }
- return true;
- /*
- можно это же написать проще
- return (copyElements.get(index).getText().contains(text))
- но - лучше так не делать
- тут - самое время зафиксировать факт(actual) - который позже выведем в toString()
- какой у нас факт - это текст такого-то элемента
- нужно что-то такое
- actualText = elements.get(index).getText();
- и уже ниже - return (actualText.contains(text))
- и этот же actualText - выведем и в toString
- это даст тебе возможность писать простой toString
- который уже ничего не ищет
- просто - выводит то, что ранее получено
- теперь давай рассудим - что нам бы было удобно увидеть в сообщении об ошибке
- я, например, хотела бы увидеть не только текст такого-то элемента
- но и все тексты всех элементво в списке
- чтобы понять - может я в индексе ошиблась
- и вот для этого - в начале apply и стоило бы собрать список строк - тексты всех элементов
- чтобы потом - для принятия решения - им оперировать
- и в toString вывести
- ну и далее размышляем
- если мы выводим и анализируем лишь actual текст такого-то элемента
- то мы вообще копию списка можем не делать
- достаточно зафиксировать actual текст такого-то элемента
- а если выводим все тексты и анализируем такой-то текст - то нам удобнее все же
- оперировать списком текстов, а не копией списка
- поэтому - как ни красива эта идея - с копированием списка
- нам она тут не пригодится)
- да, и пока не торопись реализовывать работу со списком текстов
- читай дальше - поясню почему
- */
- }
- public String toString() {
- return String.format("\nExpected text: %s\n while actual text is: %s\n", text, copyElements.get(index).getText());
- }
- };
- }
- /*
- еще момент
- когда мы выполняем elements.get(index)
- для индекса за границами списка
- может возникнуть IndexOutOfBoundsException
- и в принципе - при работе с элементами могут возникать исключения типа StaleElementReferenceException или
- ElementNotVisibleException
- и их надо внутри apply кондишена - ловить
- чтобы упростить apply кондишена - можно воспользоваться рекомендациями
- https://docs.google.com/document/d/1BiYTLdypDfucSqiY9isv1HCKKQIxelzqYrN-3Ku1RWM/edit?usp=sharing
- в качестве типа параметра для кетчера можешь использовать тип попроще
- не
- final Function<? super WebDriver, V> condition
- а
- ExpectedCondition<V> condition
- final Function<? super WebDriver, V> - это предок ExpectedCondition
- нам не обязательно оперировать им
- мы кетчер только для кондишенов будем использовать
- */
- http://joxi.ru/Vrwqg81HK6dYR2
- /*
- Вот еще пример реализации (мне в toString не нравится вывод (index+1), а не просто index,
- но это уже детали)
- 1 - применили elementExceptionsCatcher
- цель - избавиться от try-catch в самом apply
- это нам надо для того, чтобы упростить логику apply, увидеть ее без лишней мишуры
- научи elementExceptionsCatcher ловить и IndexOutOfBoundsException
- кстати - можно ловить несколько видов исключений в одной catch-секции
- так можно и в кетчере это сделать)
- http://stackoverflow.com/questions/3495926/can-i-catch-multiple-java-exceptions-in-the-same-catch-clause
- тоже тонкость)
- если выполнять return elements.get(index); -
- список же может опять переискаться) и вылезет что-то другое... ((
- как выкручиваемся
- 2 - сохраняем актуальный текст нужного нам элемента в этой переменной
- 3 - сначала получаем сам элемент (он уже не переискивается - он не лейзи прокси)
- 4 - у него получаем текст
- 5 - сверяем полученный текст
- 6 - возвращаем элемент из пункта 3 (не заново ищем в списке, а возвращаем тот же, по которому делали выводы)
- 7 - в тексте ошибки оперируем только актуальным текстом, который мы получили в пункте 4 (заново не получаем)
- при таких раскладах - если кондишен реализован как ExpectedCondition<WebElement>
- нам действительно не стоит получать все тексты
- когда будем переписывать - избавляться от лейзи прокси элементов
- то сможешь получить тексты элементов и вывести их все в toString
- тут - с лейзи прокси - чтобы так реализовать - придется глубже в дебри залезть
- и таки делать еще и копию списка вебэлементов
- не хочется)
- выводы
- 8 - возвращаем ровно тот же элемент, текст которого проверяли
- 9 - описываем проверенный в apply текст
- */
- *****************************************************
- public static ExpectedCondition<List<WebElement>> texts(final List<WebElement> elements , final String... expectedTexts) {
- return new ExpectedCondition<List<WebElement>>() {
- public List<String> actualTexts = new ArrayList<String>();
- public String str1 = "";
- public String str2 = "";
- /*
- эти 2 переменные тебе не нужны
- */
- public List<WebElement> apply(WebDriver driver) {
- /*
- сначала - очищай actualTexts или заново инициализируй
- несколько вызовов apply - и в списке - бардак)
- */
- for(int i = 0; i < elements.size(); i++ ){
- actualTexts.add(i, elements.get(i).getText());
- }
- /*
- этот цикл будет легче - если применишь
- for(WebElement element:elements)
- */
- if (actualTexts.size() == expectedTexts.length){
- for(int i = 0; i < actualTexts.size(); i++ ) {
- if (!actualTexts.get(i).contains(expectedTexts[i])) {
- return null;
- }
- }
- } else {
- return null;
- }
- return elements;
- /*
- этот кусочек можно переписать чуть проще
- ниже поясню
- */
- }
- public String toString() {
- for(int i = 0; i < actualTexts.size(); i++){
- str1 += actualTexts.get(i);
- }
- /*
- у списка строк - красивое текстовое представление
- actualTexts.toString() - уже выведет все элементы
- */
- for(int i = 0; i < expectedTexts.length; i++){
- str2 += expectedTexts[i];
- }
- /*
- по сути varargs параметр - это практически массив
- http://www.linkex.ru/java/varargs.php
- у массива - не крисивое текстовое представление
- expectedTexts.toString() - будет не красиво
- а вот Arrays.toString(expectedTexts) - будет ок)
- таким образом - код будет проще)
- */
- return String.format("\nChecked that expected container: %s\n not equal to actual container: %s\n Containers not equal", str2, str1);
- }
- };
- }
- ******************************************
- http://joxi.ru/ZrJX8Y3f14Zoz2
- /*
- вот вариант реализации
- в принципе - у тебя уже похоже все
- применение кетчера + немного логика упрощена + фраза в toString - попроще)
- 1-2-3 - этот кондишен делаем как ExpectedCondition<List<WebElement>>
- 4 - переменную actualTexts объявляем внутри анонимного класса, а не просто в методе
- причины - только внутри реализации кондишена actualTexts и нужна
- 5 - actualTexts - всегда инициализируем вначале apply
- причина - каждый вызов apply - проверка заново
- надо оперировать свежими данными
- 6 - у нас ExpectedCondition<List<WebElement>>
- когда проверка прошла - в случае успеха мы возвращаем тот же лейзи-прокси список
- 7 - когда проверка не прошла - возвращаем нулл
- 8 - в toString() - используем тот же список текстов, что сохранили в actualTexts
- apply - когда принимали решение - проверка прошла или нет
- */
- *****************************
- http://joxi.ru/krDOZldF0pJoeA
- /*
- размести эти классы в пекедже core
- core & pages - будут на одном уровне
- */
- *************************************
- public class GMailPage{
- @FindBy(css = "[role='main'] .zA")
- public List<WebElement> mail;
- /*
- вот это - как раз mails )
- */
- @FindBy(css = "[role='main']")
- public List<WebElement> mails;
- /*
- а такой список элементов - тебе не нужен )
- */
- public GMailPage(WebDriver driver){
- PageFactory.initElements(driver, this);
- }
- /*
- с конструктором - все ок
- только я бы в пейдже - разместила все вспомогательные методы
- а еще лучше
- организовать предка для пейджа
- с переменной WebDriver driver
- и в конструкторе - выполнять PageFactory.initElements(driver, this);
- и запоминать в переменной driver - переданный в конструктор driver
- https://docs.oracle.com/javase/tutorial/java/javaOO/classvars.html
- тогда - и внутри пейджей-наследников такого класса
- сможешь использовать методы, которым надо передать драйвер
- как реализовать конструктор в классах-наследниках - почитай тут
- http://developer.alexanderklimov.ru/android/java/extends.php
- подсмотри в решении селенидовском - разбивку на пейджи
- будут пейджи-объекты теперь
- но логика размещения методов, их параметры, идеи в названиях пейджей -
- все это можно использовать
- */
- }
- ************************
- public class BaseTest {
- ...
- public static WebDriverWait wait;
- /*
- тебе не нужна эта переменная
- у нас есть assertThat - и это будем использовать
- */
- **************************************
- public class GMailTest extends BaseTest {
- @BeforeClass
- public static void config() {
- Configuration.timeout = 15;
- }
- /*
- о, так ты так и делаешь - настраиваешь тут таймаут
- чего тогда такой огромный таймаут по умолчанию? )
- */
- ******************************************
- GMailPage page = new GMailPage(driver);
- /*
- да, вот таким способом и остальный пейджи создашь
- */
- *********
- public void assertMail(int index, String mailHeaderText){
- assertThat(driver, nthElementHasText(page.mail, index, mailHeaderText));
- }
- /*
- тут все ок с реализацией
- */
- *******************
- public void assertMails(String...mailHeaderText){
- assertThat(driver, texts(page.mails, mailHeaderText));
- }
- /*
- а тут почему работаешь со списком элементов по слелектору [role='main']?
- нам надо по-прежнему работать с [role='main'] .zA
- имя параметра метода
- метод позволяет работать с текстАМИ заголовков мейлов
- mailHeaderText__s__
- )
- */
Advertisement
Add Comment
Please, Sign In to add comment