Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- https://github.com/AleksanderPopov/automicianTask http://pastebin.com/fqriA6GL
- <build>
- <plugins>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-compiler-plugin</artifactId>
- <configuration>
- <source>1.8</source>
- <target>1.8</target>
- </configuration>
- </plugin>
- </plugins>
- </build>
- <dependencies>
- <dependency>
- <groupId>com.codeborne</groupId>
- <artifactId>selenide</artifactId>
- <version>4.0</version>
- </dependency>
- <!-- https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-java -->
- <dependency>
- <groupId>org.seleniumhq.selenium</groupId>
- <artifactId>selenium-java</artifactId>
- <version>3.0.1</version>
- </dependency>
- <!-- https://mvnrepository.com/artifact/org.testng/testng -->
- <dependency>
- <groupId>org.testng</groupId>
- <artifactId>testng</artifactId>
- <version>6.9.13.6</version>
- </dependency>
- </dependencies>
- /*
- Ну, несколько моментов
- логичнее - было релизовать отдельно селенидовский проект и селениусмкий - поскольку pom-ы будут разные
- Используй не TestNG, а именно JUnit
- мы на курсе именно JUnit используем
- он лаконичнее и строже, и его фукнкциональности - достаточно
- а поскольку на курсе будем использовать его - то разумнее и тебе на нем остановиться
- даже если ты настаиваешь на TestNG - рассчитывай на то, что все вопросы, с ним связанные, мы не будем помогать тебе решать
- Мы не считаем TestNG удачным выбором )
- И все вопросы по TestNG - придется тебе решать самостоятельно - как просто какие-то теоретические, так и практические
- Потому - настойчиво рекомендую для работы на курсе выбрать JUnit
- Вот тут Сергей Пирогов - касается вопросов сравнения TestNG & JUnit
- http://automation-remarks.com/budtie-ostorozhny-s-testng-lisienierami/index.html
- Вот еще интересное мнение
- http://blog.javafortesters.com/2014/09/faq-should-i-use-junit-or-testng-which.html
- Я согласна с ним в таких вопросах
- I think JUnit is easier for beginners to work with
- JUnit has more online resources to help
- I think the basic JUnit skills you learn are transferrable to TestNG, if you use that on your site
- а вот это
- Most of the production teams I have worked with use JUnit
- Я конечно не проверю)
- Но вот нашелся линк
- https://javalibs.com/compare/junit-vs-testng
- Вот тут видео Солнцева
- http://sqadays.com/en/talk/25882
- с 25-ой минуты он про это касается
- Да и вообще видео полезное)
- У Якова - аргументы похожи на аргументы Солнцева
- JUnit = “православный” = в нем есть только те фичи, которые нужны для написания
- “правильных эффективных тестов”. Такой инструмент загоняет тебя в правильные рамки
- и не позволяет отстрелить себе ногу )
- А TestNG - сборная солянка, с которой очень просто нагородить ужасов, например - зависимые тесты...
- То, что в JUnit есть фичи типа аннотации depends - это уже зло, и делает JUnit-у мегаминус в карму)
- */
- *******************************
- http://joxi.ru/krDOZldF01g9LA
- /*
- Мне не кажется хорошей идея держать в проекте хромдрайвер как ресурс
- хромдрайвер и где он расположен - свойство environment-а
- а не проекта как такового
- может - на уровне проекта еще задать путь к хромдрайверу еще ок
- но вот зашить внутрь проекта...
- я бы поспорила)
- Можно было пока подключить selenide 3.11 и использовать файрфокс 47.0.1
- ну и селениум 2.53.1 - соответственно
- Тогда не пришлось бы возиться с хромдрайвером)
- и пока нам этой конфигурации - с головой хватило бы
- этот материал поможет сориентироваться
- https://docs.google.com/document/d/1fodHkTunrtit-EiMBrb91Mc6rbnQ5LwtBL9rISQveKA/edit
- ну то уже сам решай - про версии
- в принципе - познаний у тебя достаточно
- потому - насчет версий сам решай
- */
- **************************************
- http://joxi.ru/E2pdR1lFBd40d2
- /*
- Насчет пейджа в принципе
- Тут пока применять пейджи - смысла большого не было
- Эта задача эмулирует ситуацию когда мы пишем “драфт тест” - чтобы проверить как вообще автоматизация заходит на этот новый проект -
- такой старт, потому наи пока и не нужны вспомогательные методы пейджа - степы
- особенно - если учесть - что повторений практически нету
- единственная причина почему в пейдж в таких обстоятельствах стоит реализовывать - это если сразу же тест будут смотреть мануальщики
- например - для ревью покрытия - и потому уже в этот момент нужно чтоб код был красивый и без технических деталей -
- поиска элементов и всего такого, только чистая наглядная тестовая логика
- раз уже пейдж есть - пусть будет
- это объяснения про причины/цели
- Ты много сущностей вынес в поля пейджа
- Этим тоже не надо злоупотреблять,т к это не KISS
- https://docs.google.com/document/d/13dNyFGbI7mV22UUhH8E0LJ7SzabAmX7Bw7VCHScYfiU/edit#heading=h.w4krdzi2dr1j
- правильнее создавать сущности - тогда, когда они нужны
- и если какой-то локатор используется только в одном методе - то как правило - там ему и место
- и кода меньше будет)
- это кстати - тоже одна из проблем @FindBy & PageFactory - что такой подход не позволяет писать экономно код
- правда, в Selenide таки можно - т к есть альтернатива, в отличие от Selenium
- Для проекта, написанного на Selenide - никаких аннотаций @FindBy элементов не нужно
- SelenideElement element = $(....);
- будет и переискиваться - при работе с ним
- и еще - сам дожидаться - что работать с элементом можно (клик - сначала подождет видимости элемента, например)
- не
- @FindBy(xpath = ".//ul[@id='todo-list']//li")
- private ElementsCollection tasksContainers;
- а
- private ElementsCollection tasks = $$(....);
- для пейджа Selenide - решения
- переходи на полноценное использование
- SelenideElement и ElementsCollection
- в смысле - не нужны тебе никакие @FindBy аннотации тут
- видео Якова достаточно - чтоб сориентироваться
- вот тебе еще на почитать
- http://selenide.org/documentation.html
- для пейджа Selenium-решения -
- вариант без @FindBy - тоже предпочтительнее
- вот почему:
- - гораздо менее лаконичный и менее читабельный
- - магичный и не ооп-шный - не консистентный со всем другим кодом создания прокси элементов, и вообще классов в проекте -
- а значит ньюкамерам сложнее въехать
- - Page Factory в принципе зло.
- Этого Яков касается в докладе https://www.youtube.com/watch?v=Hi6EYEkSvrk
- Page Factory вся наша тусовка кстати - считает злом.
- И Пирогов
- И Солнцев
- и главное - Баранцев (коммиттер в селениум) .
- Есть планы ее выкинуть с Селениума вообще
- Про использование xPath
- Тебе он тоже не нужен )
- css Selector-ов - почти всегда достаточно
- В этом проекте - xPath-ы тебе точно не понадобятся
- Привожу тебе наш диалог с другим струдентом)
- Почему грамотнее предпочитать cssSelectors xpath-выражениям
- student: а маска может быть написана через xpath?
- Julia Iluhina: может
- Julia Iluhina: но лучше используй цсс селектор - если есть такая возможность
- Julia Iluhina: http://stackoverflow.com/questions/16788310/what-is-the-difference-between-css-selector-xpath-which-is-betteraccording-t
- Julia Iluhina: http://elementalselenium.com/tips/32-xpath-vs-css
- Julia Iluhina: Некоторые вещи невозможно сделать без xpath
- Julia Iluhina: там конечно он пригодится)
- ...
- Iakiv Kramarenko: а если по делу - то икспасы ЗЛО, потому что громоздкие и плохо поддерживаемые
- и их стоит использовать очень редко, только когда цсс-ов не хватает
- единственное место где тебе нужны будут знания икспасов - это интервью
- потому что большинство автоматизаторов - плохие автоматизаторы) и почему то думают что икспасы это круто :)
- так вот… когда нужно будет пройти интервью - тогда и выучишь икспасы - а сейчас нечего дурным голову забивать
- Iakiv Kramarenko: On 7/26/16, at 3:27 PM, student wrote:
- > Может для икспаса другой синтаксис
- у икспаса конечно другой синтаксис
- и если ты хочешь найти элемент по икспасу нужно явно передавать в долар икспас
- так
- $(By.xpath(…))
- либо так
- $(byXpath(…))
- вот здесь я пишу об этом более подробно:
- http://automated-testing.info/t/pomogite-razobratsya-s-problemoj-czikla-v-selenide/10467/8
- */
- *********************************************
- private SelenideElement getTask(String text) {
- for (SelenideElement taskContainer : tasksContainers) {
- if (taskContainer != null && taskContainer.$(By.xpath(".//label")).getText().equalsIgnoreCase(text))
- return taskContainer;
- }
- throw new IllegalArgumentException();
- }
- /*
- Это можно проще делать
- у ElementsCollection - есть метод findBy
- который в качестве параметра получает Condition
- есть такой - exactText - который как раз найдет элемент с точно таким текстом
- в общем - все очень упростится
- в статье по выше приведенной линке - есть пример как раз
- $$("#todo-list li").findBy(exactText("4")).find(".destroy").click()
- против
- $(By.xpath("//*[@id='todo-list']//li[.//text()='4']//*[@class='destroy']").click()
- посмотри на нее)
- */
- ****************************************
- public class TodoTests {
- /*
- почитай по неймингу вот это
- https://docs.google.com/document/d/13dNyFGbI7mV22UUhH8E0LJ7SzabAmX7Bw7VCHScYfiU/edit#heading=h.c6yq8ne03bpo
- и согласно прочитанному - подправь имя тест-класса и тест-метода
- */
- @Test
- public void endToEndTest() throws InterruptedException {
- System.setProperty("webdriver.chrome.driver", ".//src//main//java//com//resources//chromedriver_2_25.exe");
- System.setProperty("selenide.browser", "chrome");
- /*
- браузер можно задавать и попроще
- Configuration.browser = "chrome";
- см http://selenide.org/faq.html
- про хромдрайвер писала - его в проекте держать не стоит вообще -
- т к это не часть реализации проекта, а свойство environment-а
- дальше на курсе будет - и как задать путь к хромдрайверу на уровне pom
- и как извне задать его при запуске проекта из командной строки
- пока ок - сама строчка System.setProperty("webdriver.chrome.driver"...
- самое важное - что нужно подправить для настроек
- такие настройки - правильнее делать ДО запуска тест-метода
- это - не тестовая логика
- это - предварительные действия
- если у тебя тесты ранятся в одном потоке - надо это задать перед запуском всех тест-методов
- если в разных - перед запуском каждого тест-метода
- в данном случае - в BeforeClass-методе было бы ОК настройки делать
- http://junit.sourceforge.net/javadoc/org/junit/BeforeClass.html
- а если вернуться к варианту selenide 3.11 и использовать файрфокс 47.0.1
- этого просто не придется делать
- */
- MainPage page = open("https://todomvc4tasj.herokuapp.com", MainPage.class);
- /*
- не знаю, стоило ли объединять создание пейджа и открытие урла
- мне это кажется перебором
- допускаю, что это личные предпочтения
- но все же)
- создание пейджа - я бы делала вне тест-метода
- из тех же соображений - создание пейджа - еще не тестовая логика сценария
- а подготовка инструментов = дело тест-класса в общем, а не тест-метода в частности
- а вот открытие урла - уже реализация самого сценария, и этот шаг точно должен происходить внутри тест-метода
- по крайней мере пока)
- пока у нас нет повода выносить открытие урла например в @Before-метод - для случая, если все тест-методы класса
- начинают свою работу с открытия этого урла
- допускаю - что вот это мое решение - все же субъективно
- тут не настаиваю
- */
- page.waitForAjaxComplete();
- /*
- вот это решение - очень интересное
- сама идея ждать таким образом пока для страницы все что нужно догрузится - она бесспорно хороша)
- кстати, ты с этой проблемой - даже и не столкнулся бы, используй ты конфигурацию selenide 3.11 и файрфокс 47.0.1 )
- хром - достаточно быстр по сравнению с файрфоксом,
- и как результат - в хроме, бывает проявляется этот момент для https://todomvc4tasj.herokuapp.com
- что элементы доступны чуть раньше - чем JavaScript подгрузится
- и когда начинают выполняться действия раньше этого момента - получаем проблемы
- такое ожидание - это, фактически, вызов селениумского new WebDriverWait(...).until
- для тобой разработанного кондишена
- по идее такая проверка - это не логика пейджа, и даже не логика предка пейджа
- т к в общем - по своей сути - вещь сравнительно универсальная и применимая в разных обстоятельствах
- я бы такие вещи рекомендовала реализовывать так
- http://joxi.ru/brRlV57uQwBEj2 - организовала специальный класс для хранения нами разработаных ExpectedCondition
- обрати внимание
- где в проекте располагается этот класс (ветка проекта src\main - т к вещь это = универсальная)
- в кондишене - реализован метод toString() - обеспечивающий нормальное сообщение в случае
- если new WebDriverWait(...).until не дождется положительного результата - http://joxi.ru/vAW36KgskY3vgA
- можно взять за основу и твое подробное сообщение - Ajax is not completed ($.active!=0)
- http://joxi.ru/Q2KpJYOs9zO6LA - класс для различных универсальных методов
- тоже - расположен там же (ветка проекта src\main)
- фактически - тут как раз вызываем наш кондишен в new WebDriverWait(...).until
- этот метод - нам подойдет для использования и в селенидовской версии, и в селениумской
- получим
- для Selenide
- Helpers.waitForAjaxIsLoaded(getWebDriver(), Configuration.timeout);
- для Selenium
- Helpers.waitForAjaxIsLoaded(driver, ...);
- и throws InterruptedException - для тест-метода уже не понадобится
- Чем такой подход лучше
- почитай про Single Responsibility principle
- каждый класс - должен решать свои задачи
- при таком подходе код будет проще, понятнее, однозначнее
- у нас будут классы
- пейдж - отвечает за инструменты для работы с конкретно такой-то страницей
- контейнер кондишенов - только содержит реализованные нами кондишены
- (которые реализуем максимально универсально - без привязки к контекстам нашего приложения)
- контейнер универсальных методов - которые можно использовать как в пейджах, так и в тест-методах
- и каждый будет заниматься своим делом)
- в результате - нам не понадобится в пейдже для решения на Selenide - использовать предка
- да и вебдрайвер пейджу не нужно передавать)
- Для селениумского предка пейджа - тоже многое изменится
- не факт - что при таких раскладах он нужен вообще
- метод waitUntilVisible(WebElement element) - тоже вещь универсальная, на самом деле
- потому держать это в предке пейджа - тоже нарушение Single Responsibility Principle
- Еще момент по пейджам
- public static int DEFAULT_TIMEOUT_SEC = 10;
- Это - настройка, касающаяся не пейджа, а самого теста
- все настроечные вещи - лучше держать или в тест-классе, или его предке
- (это зависит от того -
- что будет переиспользоваться/что нет
- что есть смысл прятать из самого тест-класса/что нет)
- Лучше выносить в предка тест-класса aka "test config" -
- чтоб не светить в тесте техничекими деталями
- ЕСЛИ - это какие-то униварсальые настройки
- */
- page.addTask("new task1")
- .addTask("new task2")
- .addTask("new task3")
- .addTask("new task4")
- .deleteTask("new task2")
- .markTaskAsCompleted("new task4")
- .clearCompletedTasks()
- .markAllTasksAsCompleted()
- .clearCompletedTasks();
- /*
- все чудесно и красиво
- но где проверки?
- нам нужно было реализовать ТЕСТ на базе сценария
- а ТЕСТ в принципе включает шаги плюс проверки
- каждое действие должно быть проверено сразу
- иногда можно отложить проверки
- но для этого должны быть причины и/или цели
- про это - вставлю кусок текста ниже
- таки посмотри Якова видео
- реализуй пока ТОЛЬКО версию для Selenide
- подправь работу с SelenideElement & ElementsCollection
- перейди на использование JUnit
- избавься от xPath
- убери из проектов chromedriver_2_25.exe
- добавь проверки)
- Видно - что навыков много
- но к их применению есть вопросы)
- раздели проекты на 2 - для Selenium & Selenide
- в pom.xml обоих проектов - не держи лишнего
- да и вообще пока Selenium - пока отложи
- закончим с Селенидовской версией сначала
- */
- }
- ********************************************************************
- driver.close();
- driver.quit();
- /*
- это по пути
- http://stackoverflow.com/questions/15067107/difference-between-webdriver-dispose-close-and-quit
- http://www.testingdiaries.com/driver-close-and-driver-quit/
- http://internetka.in.ua/selenium-webdriver-quit-or-close/
- */
- ************************************
- /*
- когда стоит или можно откладывать проверку, не делать ее сразу после действия
- в целом = правило такое = каждое действие должно быть проверено сразу
- это нужно для того, чтобы знать не только, что действие выполнено
- но и то, что действие (каждое) выполнено с ожидаемым нами результатом
- и если тест упал - нам важно знать
- какая конкретно операция этому была виной
- суть проверки - не только проверить сущность, над которой выполнялось действие
- но и общую картину
- в нашем случае могло быть так
- добавляем таску - а добавляется 2 одинаковые
- проверка - что перава таска имеет такой-то текст - пройдет
- и об ошибке мы не узнаем
- а это плохо)
- потому правильнее - проверять общую картину
- а не состояние сущности, над которой было совершено действие
- если это возможно, конечно)
- и если мы оперируем именно списком однотипных сущностей
- почему и когда мы можем отложить проверку
- первый пример - проверить первый раз список тасок уже после добавления всех 4-ех тасок
- т к операции однотипные в общем-то
- можно быть чуть точнее
- проверить список тасок после добавления первой таски и после добавления последней таски
- если посчитать - что это 2 разные ситуации = добавление первой и добавление последующих тасок
- второй пример - не делать проверки списка тасок после закомпличивания одной или всех тасок
- а уже делать проверку после следующей операции - clear completed
- тут логика следующая
- после закомпличивания таска все равно отображается в списке
- и то, что она закомпличена - мы поймем уже после выполнения clear completed
- но, с другой стороны,
- то, что закомпличивания таска все равно отображается в списке - это
- как раз часть логики....
- и из этих соображений - стоило бы тут добавить проверку
- пример - при закомпличивании таска удаляется
- если проверим аж после clear completed -
- такую ошибку не поймаем
- так что по поводу проверки после закомпличивания -
- ее нужно использовать, если операция закомпличивания нестабильна
- или ее можно отложить - если мы не ждем сюрпризов от этой операции
- такой баланс - эффективность vs точность
- */
Advertisement
Add Comment
Please, Sign In to add comment