Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- https://bitbucket.org/OlyaP/modularsimple/src/911f4a230057b81372edc511cfb94e2354e2622d/pom.xml?at=master&fileviewer=file-view-default
- https://bitbucket.org/OlyaP/todomvcseleniium/src/e3afa7ef96a26466e79ada504d550c466dfe5a32/pom.xml?at=master&fileviewer=file-view-default
- /*
- что-то многовато всякого в pom
- заглянула в предыдущие проекты - а там тоже все не очень
- по идее - должно быть достаточно вот этого
- */
- <dependencies>
- <dependency>
- <groupId>org.seleniumhq.selenium</groupId>
- <artifactId>selenium-java</artifactId>
- <version>2.53.1</version>
- </dependency>
- <dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- <version>4.12</version>
- </dependency>
- </dependencies>
- /*
- пересмотри pom в этом проекте и предыдущих по селениуму
- проверь - чтоб код остался работоспособным
- к следующей проверке этой работы - обнови линки на решения - по всем селениумским работам
- я пробегусь, посмотрю на pom
- держи в pom только то, что нужно
- иначе - можешь наловить разнообразных ошибок - при нагромождениях в pom это сделать гораздо проще
- */
- *********************************
- http://joxi.ru/82QYoQyI1LnPq2
- /*
- не держи лишнего в репозитории
- тоже - и на этот предмет посмотри селениумские работы
- раз pom-ы подправишь, то уже и это заодно
- */
- ***************************
- todomvcseleniium / .gitignore
- /target/
- /todomvcselenium.iml
- /.idea/
- /*
- а причина того, что в репозитории много лишнего - в .gitignore
- вот пример полезного .gitignore
- */
- *.iml
- .idea
- target
- build
- /*
- подправь .gitignore
- благодаря этому - не будет ненужное добавляться/обновляться
- а то лишнее, что раньше было выгружено в репозиторий - надо удалить по-другому
- https://help.github.com/articles/removing-a-remote/
- http://stackoverflow.com/questions/7927230/remove-directory-from-remote-repository-after-adding-them-to-gitignore
- http://stackoverflow.com/questions/13541615/how-to-remove-files-that-are-listed-in-the-gitignore-but-still-on-the-repositor
- https://git-scm.com/docs/git-rm
- */
- ************************************
- public static List<WebElement> $$(By elementLocator) {
- return assertThat(visibilityOfAllElementsLocatedBy(elementLocator));
- }
- public static List<WebElement> $$(String cssSelector) {
- return $$(By.cssSelector(cssSelector));
- }
- /*
- Посмотри - как устроен кондишен visibilityOfAllElementsLocatedBy
- при динамической загрузке списка такое ожидание может не помочь
- в случае с $$ - нам разного в разных случаях нужно ждать
- в отличие от $ - там хорошо и правильно ждать именно видимости элемента - там у нас более определенная ситуация
- поэтому - организация вот таких методов $$(By elementLocator) и $$(String cssSelector),
- с проверкой visibilityOfAllElementsLocatedBy - смысла не имеет
- удаляй методы
- */
- ******************************************
- public static List<WebElement> $$(ExpectedCondition<List<WebElement>> listExpectedCondition) {
- return assertThat(listExpectedCondition);
- }
- /*
- а вот такой метод - как раз более корректный
- только имя параметра странноватое
- я бы просто назвала параметр condition
- в сочетании с типом параметра - достаточно точное имя
- */
- *******************************************
- public static WebElement $(ExpectedCondition<WebElement> conditionToWaitParentElement, String cssSelectorOfInnerElement) {
- WebElement parentElement = assertThat(conditionToWaitParentElement);
- return parentElement.findElement(By.cssSelector(cssSelectorOfInnerElement));
- }
- /*
- верно организован метод
- а теперь - по аналогии
- реализуй более универсальный вариант
- $(ExpectedCondition<WebElement> conditionToWaitParentElement, By innerElementLocator)
- и в методе $(ExpectedCondition<WebElement> conditionToWaitParentElement, String cssSelectorOfInnerElement)
- переиспользуй метод $(ExpectedCondition<WebElement> conditionToWaitParentElement, By innerElementLocator)
- получится более универсально
- */
- ******************************************
- public static WebElement $(ExpectedCondition<WebElement> conditionToWaitElement, WebElement element) {
- return assertThat((ExpectedCondition<WebElement>) element);
- }
- /*
- очень странный метод
- не могу пока понять - зачем он такой
- */
- **************************
- public static WebElement $(String cssSelector) {
- return $(By.cssSelector(cssSelector));
- }
- /*
- а этот метод разумнее было расположить рядом с public static WebElement $(By elementLocator)
- когда закончишь править задание
- пройдись по ConciseAPI
- подправь полядок методов
- важно = чтобы рядом друг с другом были расположены методы, связанные друго с другом
- ну и двигайся - от общего к частному, от простого к сложному
- так код этого класса будет гораздо проще понять
- хотя технически - порядок методов ни на что не влияет
- а восприятие кода - сильно изменится
- */
- ************************************
- public class Configuration {
- public static int timeout = 4;
- public static List<String> getTexts(List<WebElement> elements) {
- List<String> actualTexts = new ArrayList<String>();
- for (WebElement element : elements) {
- actualTexts.add(element.getText());
- }
- return actualTexts;
- }
- }
- /*
- неожиданно)
- причем к конфигурационным настройкам метод, возвращающий тексты списка вебэлементов?
- это ведь просто служебный универсальный метод
- к ConciseAPI его конечно тоже не отнесешь
- реализуй класс Helpers (в пекедже core) для вот таких полезных универсальных методов
- перенеси туда этот метод
- ну и почитай про Single Responsibility Principle )
- дальше его понимание нам пригодится)
- */
- ******************************************
- public static ExpectedCondition<List<WebElement>> texts(final By elementsLocator, final String... expectedTexts) {
- if (expectedTexts.length == 0) {
- throw new IllegalArgumentException("Array of expected texts is empty.");
- }
- return elementExceptionsCatcher(new ExpectedCondition<List<WebElement>>() {
- ...
- public static ExpectedCondition<List<WebElement>> exactTexts(final By elementsLocator, final String... expectedTexts) {
- return elementExceptionsCatcher(new ExpectedCondition<List<WebElement>>() {
- ...
- /*
- в texts - мы контролируем, чтоб нам передали хотя бы один текст
- а в exactTexts и exactTextsInVisibleElements - уже нет
- я помню про exactTexts и exactTextsInVisibleElements
- мы так реализовали - чтобы использовать это в кондишенах
- isNoVisibleElements(By locator) и isNoElements(By locator)
- да, в этой версии - это решение приемлемо (как вариант - когда мы не пишем лишнего кода,
- не раздуваем решение. Но надо признать, не самое наглядное или простое такое решение)
- В следующих работах - сделаем нагляднее. Там к тому же - нам удастся и лаконичными остаться
- Тут - это ок
- но - хорошо бы, чтобы логика кондишенов texts и exactTexts и exactTextsInVisibleElements
- отличалась исключительно значимыми моментами (способом сравнения текстовб или тем,
- к каким элементам списка кондишен применяется - всем или только видимым)
- а вносить еще и такие различия - как контроль количества переданных текстов - это слишком сложно
- да и не объяснимо) - почему в одном кондишене мы сделали такую проверку, а в другом - нет
- советую тебе эту проверку закомментить
- потом - нам этот закомменченный код пригодится
- а тут - пока мы хитрим с реализацией isNoVisibleElements(By locator) и isNoElements(By locator)
- лучше оставить кондишены texts и exactTexts и exactTextsInVisibleElements реализованными единообразно
- */
- **************************
- visibleElements = new ArrayList<>();
- for (int i = 0; i < elements.size(); i++) {
- if (elements.get(i).isDisplayed()) {
- visibleElements.add(elements.get(i));
- }
- }
- /*
- этот код - тоже стоит вынести в отдельный метод - List<WebElement> getVisibleElements(List<WebElement> elements)
- расположи такой метод там же, где и getTexts расположен
- благодаря такому реению - код кондишена станет проще
- */
- ************************************
- public static ExpectedCondition<List<WebElement>> exactTextsInVisibleElements(final By elementsLocator, final String... expectedTexts) {
- ...
- int actualVisibleSize = actualVisibleTexts.size();
- /*
- без этой переменной можно обойтись
- ты далее по коду можешь применять actualVisibleTexts.size()
- */
- if (actualVisibleTexts.size() != expectedTexts.length) {
- return null;
- }
- /*
- раз мы в if-блоке - выполняем return
- */
- else {
- /*
- то последующий код можно писать не в else-блоке
- это упростит структуру метода - он будет проще восприниматься
- */
- ...
- ****************************
- public static ExpectedCondition<WebElement> listElementHasExactText(final By elementsLocator, final String expectedText) {
- if (expectedText == "") {
- throw new IllegalArgumentException("expected texts is empty.");
- }
- /*
- тут - точно такой проверки делать не стоит
- вполне может быть - что нам надо найти элемент с пустым текстом
- это вполне штатная ситуация
- в texts и подобных кондишенах
- мы проверяя что передали хоть сколько-то текстов -
- страховали себя от использования кондишена - когда ему на вход не передано ни одного текста
- да, ты придумала, как это использовать в своих целях)
- но в общем - странный способ проверки текстов - при условии что текстов вообще не передали
- с решением по texts и exactTexts и exactTextsInVisibleElements я с тобой согласилась - там
- возвращать проверку количества текстов не надо
- просто объясняю разницу между этой ситуацией
- и ситуацией в texts и exactTexts и exactTextsInVisibleElements
- */
- ...
- public String toString() {
- return String.format("\n locator %s\n should contain exact text: %s\n while actual texts are: \n%s ",
- elementsLocator, expectedText, actualTexts);
- }
- /*
- фраза странная )
- корректнее - что-то вот такое
- element of list found by locator ....
- should have exact text ...
- while actual texts are
- */
- ******************************************
- public static ExpectedCondition<WebElement> listElementContainsClass(final By elementsLocator, final String expectedClassName) {
- if (expectedClassName == "") {
- throw new IllegalArgumentException("expected texts is empty.");
- }
- /*
- то же самое про проверку
- тут она не нужна
- да и фраза про ошибку не соотвествовала действительности
- эти мелочи могут в итоге сильно испортить жизнь
- потом сообщения про ошибки - толком ничего не дадут для понимания - что же у нас
- пошло не так
- */
- ...
- actualTexts = getTexts(elements);
- for (int i = 0; i < actualTexts.size(); i++) {
- if (actualTexts.get(i).getClass().toString().contains(expectedClassName)) {
- /*
- мы уже обсуждали это с тобой
- да и в listVisibleElementContainsClass ты применила правильные приемы
- actualTexts.get(i) - это строка
- actualTexts.get(i).getClass() - это класс String
- нам разве это нужно для анализа?
- такой кондишен тебе не нужен)
- смело прибивай его
- */
- *****************************
- public static ExpectedCondition<WebElement> listVisibleElementContainsClass(final By elementsLocator, final String expectedClassName) {
- if (expectedClassName == "") {
- throw new IllegalArgumentException("expected texts is empty.");
- }
- /*
- эта проверка - не нужна
- мотивы - такие же, как описывала выше
- что касается имени и сути реализации
- вспомни вариант селенидовский
- разве мы фильтровали список тасок по visible перед тем как искать таску с классом editing?
- мы просто в списке искали элемент с нужным нам классом
- да и здесь ты также искала)
- просто имя кондишена - не точное
- переименуй кондишен
- с listVisibleElementContainsClass
- на listElementHasCssClass
- а параметр expectedClassName
- на expectedCssClass / expectedCssClassName
- */
- return elementExceptionsCatcher(new ExpectedCondition<WebElement>() {
- private List<String> actualClasses;
- private List<WebElement> elements;
- /*
- этот список - нужен только внутри apply
- вот там его и стоит объявить
- */
- public WebElement apply(WebDriver driver) {
- elements = driver.findElements(elementsLocator);
- actualClasses = new ArrayList<String>();
- int j = 0;
- /*
- а нужна эта переменная?
- */
- for (WebElement element : elements) {
- String actualClass = element.getAttribute("class");
- actualClasses.add(actualClass);
- /*
- можно переписать в одну строку
- actualClasses.add(element.getAttribute("class"));
- */
- }
- ...
- public String toString() {
- return String.format("\n element of list found by locator %s\n should contain exact class: %s\n while actual calsses are: \n%s ",
- elementsLocator, expectedClassName, actualClasses);
- }
- /*
- should contain exact class -> should have cssClass
- while actual calsses are -> while actual elements classes are
- */
- ************************************************
- public static ExpectedCondition<WebElement> exactTextOf(final By elementLocator, final String expectedText) {
- if (expectedText == "") {
- throw new IllegalArgumentException("expected texts is empty.");
- }
- /*
- проверка не нужна - те же причины, что выше описывала
- логика имени кондишена
- если у нас texts и exactTexts и exactTextsInVisibleElements
- то разумнее не exactTextOf, а exactText
- чтоб уже единообразно
- */
- return elementExceptionsCatcher(new ExpectedCondition<WebElement>() {
- private String actualText;
- private WebElement element;
- /*
- element используется только в apply -
- там его и объявляй
- */
- public WebElement apply(WebDriver driver) {
- element = driver.findElement(elementLocator);
- actualText = element.getText();
- if (actualText.equals(expectedText)) {
- return element;
- }
- return null;
- /*
- вот это - можно переписать
- return (actualText.equals(expectedText)) ? element : null;
- гугли ternary operator java
- */
- }
- public String toString() {
- return String.format("\n locator %s\n should contain exact text: %s\n while actual text is: \n%s ",
- elementLocator, expectedText, actualText);
- }
- /*
- element found by locator ...
- should have exact text ...
- while actual text is ...
- */
- });
- }
- **********************************************
- $(By.id("new-todo")).clear();
- $(By.id("new-todo")).sendKeys(taskText, Keys.ENTER);
- /*
- реализуй в ConciseAPI метод setValue(WebElement element, ....)
- (какой тип у второго параметра - посмотри на сигнатуру sendKeys)
- в котором для элемента вызовешь clear() и sendKeys(...)
- чтобы использовать его как setValue($(By.id("new-todo")), taskText, Keys.ENTER)
- */
- ************************************
- public static void hover(WebElement element) {
- Actions action = new Actions(getDriver());
- action.moveToElement(element).perform();
- }
- ...
- public static void doubleClick(WebElement element) {
- Actions action = new Actions(getDriver());
- action.doubleClick(element).perform();
- }
- /*
- методы - универсальные
- переноси их в ConciseAPI
- можешь кстати реализовать Actions actions()
- возвращающий new Actions(getDriver())
- и тут его применять
- в обоих методах
- */
- *******************************
- public static By tasks = By.cssSelector("#todo-list li");
- ...
- public static void assertTasks(String... tasksTexts) {
- $$(By.id("todo-list li")).contains(tasksTexts);
- }
- /*
- у нас уже есть переменная tasks
- да и вариант By.id("todo-list li") - не рабочий
- т к id = todo-list, li - ни при чем к id
- что касается кода $$(...).contains(...);
- такой код - делает вот что
- у нас есть список List<WebElement> - получили в результате $$(...)
- и теперь метод contains списка - проверяет - есть ли в списке єлементі, равніе тому, что мі передали в contains
- и вернет такая проверка boolean-значение - да или нет
- в нашем случае - вернет нет
- т к среди вебэлементов точно нету массива строк)
- что в тесте есть проверка
- в случае прохождения проверки - тест работает дальше
- иначе - он должен упасть
- именно так работает assertThat
- и ему на вход - надо дать кондишен
- он у тебя тоже есть) - exactTexts
- */
- *****************************
- public static void assertVisibleTasks(String... tasksTexts) {
- $$(exactTextsInVisibleElements(tasks, tasksTexts));
- }
- public static void assertNoTasks() {
- assertThat(isNoElements(By.cssSelector("#todo-list li")));
- }
- public static void assertNoVisibleTasks() {
- assertThat(isNoVisibleElements(By.cssSelector("#todo-list li")));
- }
- /*
- а вот тут уже ок assertThat применяешь
- не забывай про переменную By tasks = By.cssSelector("#todo-list li");
- используй ее
- не надо в коде заново писать By.cssSelector("#todo-list li")
- это не DRY
- */
- ***********************************
- public static WebElement startEdit(String oldTaskText, String newTaskText) {
- ...
- WebElement element = ....
- element.clear();
- element.sendKeys(newTaskText);
- return element;
- }
- /*
- тут тоже тебе пригодится метод setValue (если делала все по ревью - он уже в ConciseAPI есть у тебя)
- */
- ********************************
- public static void ensureSiteOpened(Filter filter) {
- if (!(url().equals(filter.toString()))) {
- open(filter.toString());
- }
- $(newTask).isDisplayed();
- /*
- $(newTask) - уже ждем видимости
- isDisplayed() - возвращаем да/нет
- у нас было в селенидовской версии - мы ждали enabled
- в селениуме есть подобный кондишен elementToBeClickable
- https://seleniumhq.github.io/selenium/docs/api/java/org/openqa/selenium/support/ui/ExpectedConditions.html#elementToBeClickable-org.openqa.selenium.By-
- тут будет assertThat для элемента с локатором newTask и нужного кондишена
- */
- ***************************************
- public static <T> T executeJavaScript(String jsCode, Object... arguments) {
- return (T) ((JavascriptExecutor) getDriver()).executeScript(jsCode, arguments);
- }
- /*
- перенеси метод в ConciseAPI
- */
- ***************************************
- public class TodoMvc extends ConciseAPI {
- ...
- public class BaseTest extends ConciseAPI {
- /*
- а это ты не с того бренча подсмотрела)
- вспомни - как мы уже в прошлой работе реализовали
- https://bitbucket.org/OlyaP/modularsimple/src/ef4316c6648e?at=modularsimple
- мы не наследовали пейджей и тест-классы от ConciseAPI
- ConciseAPI = просто контейнер статических полезных методов и хранилище для вебдрайвера
- */
- ****************************************
- public static final String URL = "https://todomvc4tasj.herokuapp.com/";///
- /*
- урл прописан в пейдже
- не надо дублировать его и здесь, в BaseTest
- кроме того - хорошо бы оставить BaseTest универсальным, непривязанным к нюансам приложения
- вот в прошлой работе - идеальный универсальный BaseTest
- */
- @BeforeClass
- public static void configTimeout() {
- Configuration.timeout = 15;
- setDriver(new FirefoxDriver());
- }
- /*
- начнем с того, что для todoMVC не нужен такой таймаут
- да и если бы и был нужен - вспомни - где это делать грамотнее
- явно не в BaseTest
- имя метода - не отражает того что он делает
- а как перенесешь/уберешь Configuration.timeout = 15; - так и вообще не будет отражать)
- */
- ************************
- @Test
- public void testEditCancelAtAll() {
- given(All_FILTER);
- add("a");
- filterAll();
- /*
- не понятно)
- почему не given(All_FILTER, "a");
- для чего тогда с гивенами заводились)
- */
- ****************************
- @Test
- public void testEditAtActive() {
- givenAtActive(aTask(TaskType.ACTIVE, "b"));
- filterActive();
- /*
- тут тоже самое)
- givenAtActive - уже мы на Active
- */
Advertisement
Add Comment
Please, Sign In to add comment