Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- очень эффективно применил знания из предыдущих селениумских заданий)
- это ты молодец)
- будем улучшать)
- еще надо принять решение - будешь ти ты при улучшении реализации этого задания работать
- с элементами аннотированными @FindBy
- далее - точно уже с этим работать не будем
- из этих соображений - стоило бы познакомиться с ними поближе)
- т к может пригодиться на приктике - стоит понимать как с ними работать
- но на самом деле - их использование мало что дает...
- так что - на твой выбор)
- */
- *********************************************
- public class GMailTest {
- public static WebDriver driver = new FirefoxDriver();
- /*
- драйвер создал - это ок
- в селениуме - надо самостоятельно заботиться о его закрытии
- раз ты driver объявил статической переменной - то инициализация переменной произойдет перед
- запуском всех тест-методов класса
- значит - закрывать вебдрайвер надо в методе @AfterClass
- а что вызвать для вебдрайвера - close vs 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/
- вот эта функциональность - драйвер, его создание и удаление - нужна в любом тест-классе
- и ее стоит вынести в предка тест-класса
- чтобы это можно было переиспользовать
- */
- /*
- на самом деле - у нас есть варианты - когда создавать и вогда закрывать вебдрайвер
- выше предложенный вариант - тут самый оптимальный
- тут - опишу - что мы вообще можем, и как лучше
- чтоб не путаться, всегда при проектировании придерживайся принципов
- метод создающий и метод удаляющий - располагай в одном классе
- позаботься о соотвествующих друг другу способах вызова таких методов
- если создали в BeforeClass, то убили в AfterClass
- (это вариант = создали перед запуском всех тест-методов класса и убили после того,
- как все тесты отработали)
- вызов BeforeClass можно заменить на инициализацию статического поля или
- static initialization block
- если создали в Before, то убили в After
- (это вариант - перед запуском каждого тест-методы создали,
- после того как тест-метод отработал - убили
- такой вариант хорош для запусков тест-методов в параллельных потоках, это потом будет)
- вызов Before можно заменить на инициализацию НЕ статического поля или
- instance initialization block
- про это - ниже чуть подробнее распишу
- полезные линки для бОльшего углубления понимания
- http://stackoverflow.com/questions/15493189/beforeclass-vs-static
- http://www.unknownerror.org/opensource/junit-team/junit/q/stackoverflow/512184/best-practice-initialize-junit-class-fields-in-setup-or-at-declaration
- http://www.javaworld.com/article/2076265/testing-debugging/junit-best-practices.html
- (подзаголовок Do not use the test-case constructor to set up a test case)
- */
- ********************************************
- @Test
- public void basicEmailLifeCycle() {
- /*
- к реализации самого тест-метода - вопросо нет)
- будем разбираться со вспомогательными методами
- */
- ******************************************************
- public WebElement $(By searchByText){
- return new WebDriverWait(driver, Configuration.timeout).until(visibilityOfElementLocated(searchByText));
- }
- public By byText(String seaarchText){
- return By.xpath(".//*[text() = \"" + seaarchText + "\"]");
- }
- /*
- эти 2 метода - явно могут пригодиться не только для конкретного тест-класса
- они универсальны )
- да, для реализации метода $ - нам нужен вебдрайвер
- пока это решим еще одним дополнительным параметром метода
- у нас будет метод
- не WebElement $(By searchByText)
- а WebElement $(WebDriver driver, By elementLocator)
- обрати внимание на имя второго параметра
- такой метод мы сможем вынести в класс-контейнер универсальных статических методов
- давай его назовем ConciseAPI
- как и все универсальное - его правильно расположить в ветке проекта src \ main
- (там, где сейчас класс Helpers расположен)
- как следствие - туда же нужно переместить и класс Configuration
- ну и это просто правильно - т к это тоже универсальная штука )
- кстати, правильнее в самом Configuration выставить таймаут в более общепринятое значение
- например, в селениде - это было 4 секунды
- а в самом тест-классе - уже установить бОльший таймаут
- вспомни - как ты это же делал в аналогичном селенидовском проекте
- метод By byText(String seaarchText)
- тоже пусть будет методом из ConciseAPI
- только подравняй имя параметра
- речь про текст элемента
- можно text, elementText
- также - можно реализовать методы
- byCss - чтоб сократить By.cssSelector
- byTitle / byExactTitle - чтоб упростить
- By.cssSelector("[title='...']")
- By.cssSelector("[title~=...]")
- и метод $ с параметром String cssSelector (ну и еще один параметр - вебдрайвер, конечно)
- чтоб вместо $(By.cssSelector("..."))
- использовать $(driver, "...")
- примени разработанные методы в коде вспомогательных методов
- */
- /*
- итог
- логику работы с вебдрайвером - спрятали в предке тест-класса
- вспомогательные универсальные методы - вынесли в отдельный класс ConciseAPI
- минус - в некоторых методах, требующих вебдрайвер, пришлось добавить еще один параметр
- мы этот минус в следующих заданиях уберем
- пока - будем мириться с ним)
- уже код упростится
- дальше упрощаем)
- */
- ******************************************
- public void visit(){
- driver.get("http://gmail.com");
- }
- /*
- в ConciseAPI реализуй метод open(WebDriver driver, String url)
- и тут его используй
- */
- ****************************
- public void refresh(){
- $(By.className("asf")).click();
- }
- /*
- это можно будет переписать проще - передать методу $
- не By.className("asf")
- а цсс селектор ".asf"
- */
- **********************************************
- public void assertMail(int index, String mailHeaderText){
- new WebDriverWait(driver, Configuration.timeout).until(textToBePresentInElementLocated(By.cssSelector("[role='main'] .zA:nth-child(" + index+1 + ")"), mailHeaderText));
- }
- public void assertMails(String... mailHeaderText){
- for(String text : mailHeaderText)
- new WebDriverWait(driver, Configuration.timeout).until(textToBePresentInElementLocated(By.cssSelector("[role='main'] .zA"), text));
- }
- /*
- ну ... выкрутился)
- и почти что этого хватило)
- для assertMails - надо было при такой реализации еще и размер списка проверить)
- но - не торопись это добавлять
- мы пойдем немного другим путем
- new WebDriverWait(driver, Configuration.timeout).until(...) - такого рода код мы уже и в методе
- $ использовали
- давай в ConciseAPI реализуем метод
- void assertThat(WebDriver driver, ExpectedCondition condition)
- в котором - собственно и будет вызов
- new WebDriverWait(driver, Configuration.timeout).until(condition)
- этот метод можно будет использовать в assertMail и assertMails
- но - хотелось бы еще и реализацию метода $ упростить
- там у нас код
- return new WebDriverWait(driver, Configuration.timeout).until(visibilityOfElementLocated(searchByText))
- т е - мы возвращаем то, что возвращает нам until
- а он - возвратить может значения разных типов
- все зависит от того, какой кондишен мы ему передадим
- если ExpectedCondition<WebElement> - то until вернет WebElement
- если ExpectedCondition<Boolean> - то until вернет Boolean
- можно конечно реализовать несколько assertThat
- WebElement assertThat(WebDriver driver, ExpectedCondition<WebElement> condition)
- Boolean assertThat(WebDriver driver, ExpectedCondition<Boolean> condition)
- но - в Java есть способ поинтереснее )
- Погугли java generic method
- Вот статья на русском, сравнительно понятная
- http://www.quizful.net/post/java-generics-tutorial
- Вместо таких нескольких методов можно сделать один такой
- public <V> void assertThat(WebDriver driver, ExpectedCondition<V> condition) {
- (new WebDriverWait(driver, Configuration.timeout)).until(condition);
- }
- отличия - при объявлении такого метода мы говорим, что пока не знаем какой тип будет использоваться у
- параметра типа ExpectedCondition<...>
- это нам даст как раз возможность использовать один метод вместо нескольких -
- у которых в ExpectedCondition<...>
- явно задан тип
- и тогда метод $ тоже упростится
- public WebElement $(WebDriver driver, By locator) {
- return assertThat(driver, visibilityOfElementLocated(locator));
- }
- еще - приведу пояснения Якова по этой теме
- */
- /*
- Давай разберемся. Сначала "идейно".
- Этот метод until возвращает такую интересную динамическую штуку-аватар...
- "воплощение" которого зависит от того что именно ты передашь вейт антилу параметром
- - точнее - какой именно кондишен ты ему передаешь...
- А кондишены бывают "разные"... "Разность" эта определеятся "параметром типа" который в джава записывается
- ИмяТипа<ЗДЕСЬ>
- Ты уже ведь использовал списки, например...
- В частности - List<WebElement>
- вот в такой записи типа - его параметром, выступает WebElement, указывая джаве,
- что это не просто список, а "список ВебЕлементов"
- а мог бы быть и списком стрингов например - List<String> или еще чего :)
- Такие "умные" типы которые получают параметр (или несколько параметров) - так и называются - параметризированными
- (а фича языка, в которой они поддерживаются называется - параметрическим полиформизмом -
- не путать с тем другим полиморфмизом... который называется - subtyping polymorphism,
- а в джава все его знают как просто "полиморфизм")...
- Еще они называются - шаблоны... или дженерики...
- Именно так - Java Generics - их принято называть в Java
- Так вот... таким же дженериком является тип ExpectedCondition
- который может быть параметризирован...
- Ты уже встречал запись типа:
- ExpectedCondition<Boolean>
- что же значит этот булеан? что он параметризирует?
- А он параметризирует внутреннюю реализацию этого кондишена...
- Он определяет то, каким должен быть тип возвращаемого значения в методе apply
- То есть...
- Если ты поставишь цель создать кондишен ExpectedCondition<Boolean> - ты должен будешь реализовать
- его метод apply - как возвращающий тип Boolean
- Но зачем вообще нам париться о типе возвращаемой сущности метода apply?
- А потому, что есть еще один "умный дженерик"...
- Только который не "параметризированный класс", а "параметризированный метод"
- (в джава бывают как Generic Types так и Generic Methods)
- и этот параметризированный метод - как раз и есть наш wait.until
- особенность реализации этого метода в том... что он вызывает внутри метод apply
- нашего кондишена... и запоминает то значение, которое этот метод apply возвращает...
- И потом... в конце всей истории... этот метод until - либо бросит исключение
- (в случае если "не дождется" кондишена)
- либо вернет то, что вернул метод apply в "случае успеха"...
- Получается... Если ты передашь вейт антилу кондишен параметризированный типом Boolean
- то в случае успеха антил - вернет тру...
- то есть ты можешь писать код вида:
- if (wait.until(enabled(composeButton))) {
- doSomething();
- }
- но на самом деле, такое нужно не часто...
- то есть - такие кондишены - которые
- параметризированы типом булеан...
- бошьше толку как раз от кондишенов параметризированных типом "того, характеристики чего ждет кондишен"...
- вот кондишен visibilityOf - как раз параметризирован типом WebElement
- ExpectedCondition<WebElement>
- и его метод apply возвращает обьект типа WebElement,
- а "идейно" - возвращает этот же элемент, визибилити которого мы дожидались...
- (если бы мы не дождались - apply вернул бы null - что в этом случае играет роль "false")
- а until в конце концов вернет то, что вернет apply
- и именно поэтому мы можем писать такой код:
- wait.until(visibilityOf(composeButton)).click()
- */
- /*
- Что почитать про Generics
- про дженерики в общем(русский)
- http://www.quizful.net/post/java-generics-tutorial
- http://www.tutorialspoint.com/java/java_generics.htm
- http://developer.alexanderklimov.ru/android/java/generic.php
- конвеншенcы http://stackoverflow.com/questions/2900881/generic-type-parameter-naming-convention-for-java-with-multiple-chars
- https://docs.oracle.com/javase/tutorial/java/generics/types.html
- уроки
- http://docs.oracle.com/javase/tutorial/extra/generics/index.html
- очень приличный faq (есть pdf, и есть кое-что еще, помимо дженериков)
- http://www.angelikalanger.com/GenericsFAQ/JavaGenericsFAQ.html
- */
- /*
- пока тольк вот это подправь
- дальше продолжим
- это еще не все)
- */
Advertisement
Add Comment
Please, Sign In to add comment