julia_v_iluhina

Untitled

Oct 24th, 2016
88
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 27.87 KB | None | 0 0
  1. https://bitbucket.org/OlyaP/modularsimple/src/911f4a230057b81372edc511cfb94e2354e2622d/pom.xml?at=master&fileviewer=file-view-default
  2. https://bitbucket.org/OlyaP/todomvcseleniium/src/e3afa7ef96a26466e79ada504d550c466dfe5a32/pom.xml?at=master&fileviewer=file-view-default
  3.  
  4. /*
  5.     что-то многовато всякого в pom
  6.  
  7.     заглянула в предыдущие проекты - а там тоже все не очень
  8.  
  9.     по идее - должно быть достаточно вот этого
  10. */
  11. <dependencies>
  12.     <dependency>
  13.         <groupId>org.seleniumhq.selenium</groupId>
  14.         <artifactId>selenium-java</artifactId>
  15.         <version>2.53.1</version>
  16.     </dependency>
  17.     <dependency>
  18.         <groupId>junit</groupId>
  19.         <artifactId>junit</artifactId>
  20.         <version>4.12</version>
  21.     </dependency>
  22. </dependencies>
  23. /*
  24.     пересмотри  pom в этом проекте и предыдущих по селениуму
  25.     проверь - чтоб код остался работоспособным
  26.  
  27.     к следующей проверке этой работы - обнови линки на решения - по всем селениумским работам
  28.     я пробегусь, посмотрю на pom
  29.  
  30.     держи в pom  только то, что нужно
  31.     иначе - можешь наловить разнообразных ошибок - при нагромождениях в pom это сделать гораздо проще
  32. */
  33. *********************************
  34. http://joxi.ru/82QYoQyI1LnPq2
  35. /*
  36.     не держи лишнего в репозитории
  37.  
  38.     тоже - и на этот предмет посмотри селениумские работы
  39.     раз pom-ы подправишь, то уже и это заодно
  40. */
  41. ***************************
  42. todomvcseleniium / .gitignore
  43.  
  44.  
  45. /target/
  46. /todomvcselenium.iml
  47. /.idea/
  48.  
  49. /*
  50.     а причина того, что в репозитории много лишнего - в .gitignore
  51.  
  52.     вот пример полезного .gitignore
  53. */
  54. *.iml
  55. .idea
  56. target
  57. build
  58. /*
  59.     подправь .gitignore
  60.     благодаря этому - не будет ненужное добавляться/обновляться
  61.  
  62.     а то лишнее, что раньше было выгружено в репозиторий - надо удалить по-другому
  63.  
  64.  
  65.     https://help.github.com/articles/removing-a-remote/
  66.     http://stackoverflow.com/questions/7927230/remove-directory-from-remote-repository-after-adding-them-to-gitignore
  67.     http://stackoverflow.com/questions/13541615/how-to-remove-files-that-are-listed-in-the-gitignore-but-still-on-the-repositor
  68.  
  69.     https://git-scm.com/docs/git-rm
  70. */
  71. ************************************
  72.     public static List<WebElement> $$(By elementLocator) {
  73.         return assertThat(visibilityOfAllElementsLocatedBy(elementLocator));
  74.     }
  75.  
  76.     public static List<WebElement> $$(String cssSelector) {
  77.         return $$(By.cssSelector(cssSelector));
  78.     }
  79. /*
  80.     Посмотри - как устроен кондишен visibilityOfAllElementsLocatedBy
  81.     при динамической загрузке списка такое ожидание может не помочь
  82.     в случае с $$ - нам разного в разных случаях нужно ждать
  83.     в отличие от $ - там хорошо и правильно ждать именно видимости элемента - там у нас более определенная ситуация
  84.  
  85.     поэтому - организация вот таких методов $$(By elementLocator) и $$(String cssSelector),
  86.     с проверкой  visibilityOfAllElementsLocatedBy - смысла не имеет
  87.  
  88.     удаляй методы
  89. */
  90. ******************************************
  91.   public static List<WebElement> $$(ExpectedCondition<List<WebElement>> listExpectedCondition) {
  92.         return assertThat(listExpectedCondition);
  93.   }
  94. /*
  95.     а вот такой метод - как раз более корректный
  96.     только имя параметра странноватое
  97.     я бы просто назвала параметр condition
  98.  
  99.     в сочетании с типом параметра - достаточно точное имя
  100. */
  101. *******************************************
  102.  public static WebElement $(ExpectedCondition<WebElement> conditionToWaitParentElement, String cssSelectorOfInnerElement) {
  103.         WebElement parentElement = assertThat(conditionToWaitParentElement);
  104.         return parentElement.findElement(By.cssSelector(cssSelectorOfInnerElement));
  105.  }
  106. /*
  107.     верно организован метод
  108.  
  109.     а теперь - по аналогии
  110.     реализуй более универсальный вариант
  111.     $(ExpectedCondition<WebElement> conditionToWaitParentElement, By innerElementLocator)
  112.  
  113.     и в методе $(ExpectedCondition<WebElement> conditionToWaitParentElement, String cssSelectorOfInnerElement)
  114.     переиспользуй метод  $(ExpectedCondition<WebElement> conditionToWaitParentElement, By innerElementLocator)
  115.  
  116.     получится более универсально
  117. */
  118. ******************************************
  119. public static WebElement $(ExpectedCondition<WebElement> conditionToWaitElement, WebElement element) {
  120.      return assertThat((ExpectedCondition<WebElement>) element);
  121. }
  122. /*
  123.     очень странный метод
  124.     не могу пока понять - зачем он такой
  125.  
  126. */
  127. **************************
  128. public static WebElement $(String cssSelector) {
  129.     return $(By.cssSelector(cssSelector));
  130. }
  131. /*
  132.     а этот метод разумнее было расположить рядом с public static WebElement $(By elementLocator)
  133.  
  134.     когда закончишь править задание
  135.     пройдись по ConciseAPI
  136.     подправь полядок методов
  137.  
  138.     важно = чтобы рядом друг с другом были расположены методы, связанные друго с другом
  139.     ну и двигайся - от общего к частному, от простого к сложному
  140.  
  141.     так код этого класса будет гораздо проще понять
  142.  
  143.     хотя технически - порядок методов ни на что не влияет
  144.  
  145.     а восприятие кода - сильно изменится
  146.  
  147. */
  148. ************************************
  149. public class Configuration {
  150.     public static int timeout = 4;
  151.  
  152.     public static List<String> getTexts(List<WebElement> elements) {
  153.         List<String> actualTexts = new ArrayList<String>();
  154.  
  155.         for (WebElement element : elements) {
  156.             actualTexts.add(element.getText());
  157.         }
  158.         return actualTexts;
  159.     }
  160. }
  161. /*
  162.     неожиданно)
  163.  
  164.     причем к конфигурационным настройкам метод, возвращающий тексты списка вебэлементов?
  165.     это ведь просто служебный универсальный метод
  166.     к ConciseAPI его конечно тоже не отнесешь
  167.     реализуй класс Helpers (в пекедже core) для вот таких полезных универсальных методов
  168.     перенеси туда этот метод
  169.  
  170.     ну и почитай про Single Responsibility Principle )
  171.     дальше его понимание нам пригодится)
  172.  
  173. */
  174. ******************************************
  175.     public static ExpectedCondition<List<WebElement>> texts(final By elementsLocator, final String... expectedTexts) {
  176.         if (expectedTexts.length == 0) {
  177.             throw new IllegalArgumentException("Array of expected texts is empty.");
  178.         }
  179.  
  180.         return elementExceptionsCatcher(new ExpectedCondition<List<WebElement>>() {
  181.     ...
  182.  
  183.     public static ExpectedCondition<List<WebElement>> exactTexts(final By elementsLocator, final String... expectedTexts) {
  184.  
  185.         return elementExceptionsCatcher(new ExpectedCondition<List<WebElement>>() {
  186.     ...
  187. /*
  188.     в texts - мы контролируем, чтоб нам передали хотя бы один текст
  189.     а в exactTexts и exactTextsInVisibleElements - уже нет
  190.  
  191.     я помню про exactTexts и exactTextsInVisibleElements
  192.     мы так реализовали - чтобы использовать это в кондишенах
  193.     isNoVisibleElements(By locator) и isNoElements(By locator)
  194.  
  195.     да, в этой версии - это решение приемлемо (как вариант - когда мы не пишем лишнего кода,
  196.     не раздуваем решение. Но надо признать, не самое наглядное или простое такое решение)
  197.     В следующих работах - сделаем нагляднее. Там к тому же - нам удастся и лаконичными остаться
  198.     Тут - это ок
  199.  
  200.     но - хорошо бы, чтобы логика кондишенов texts и exactTexts и exactTextsInVisibleElements
  201.     отличалась исключительно значимыми моментами (способом сравнения текстовб или тем,
  202.     к каким элементам списка кондишен применяется - всем или только видимым)
  203.     а вносить еще и такие различия - как контроль количества переданных текстов - это слишком сложно
  204.     да и не объяснимо) - почему в одном кондишене мы сделали такую проверку, а в другом - нет
  205.  
  206.     советую тебе эту проверку закомментить
  207.     потом - нам этот закомменченный код пригодится
  208.     а тут - пока мы хитрим с реализацией isNoVisibleElements(By locator) и isNoElements(By locator)
  209.     лучше оставить кондишены texts и exactTexts и exactTextsInVisibleElements реализованными единообразно
  210.  
  211. */
  212. **************************
  213.                 visibleElements = new ArrayList<>();
  214.  
  215.                 for (int i = 0; i < elements.size(); i++) {
  216.                     if (elements.get(i).isDisplayed()) {
  217.                         visibleElements.add(elements.get(i));
  218.                     }
  219.                 }
  220. /*
  221.     этот код - тоже стоит вынести в отдельный метод - List<WebElement> getVisibleElements(List<WebElement> elements)
  222.     расположи такой метод там же, где и getTexts расположен
  223.  
  224.     благодаря такому реению - код кондишена станет проще
  225. */
  226. ************************************
  227. public static ExpectedCondition<List<WebElement>> exactTextsInVisibleElements(final By elementsLocator, final String... expectedTexts) {
  228.  
  229.         ...
  230.                 int actualVisibleSize = actualVisibleTexts.size();
  231.                 /*
  232.                     без этой переменной можно обойтись
  233.                     ты далее по коду можешь применять actualVisibleTexts.size()
  234.                 */
  235.  
  236.                 if (actualVisibleTexts.size() != expectedTexts.length) {
  237.                     return null;
  238.                 }
  239.                 /*
  240.                     раз мы в if-блоке - выполняем return
  241.                 */
  242.                  else {
  243.                  /*
  244.                     то последующий код можно писать не в else-блоке
  245.                     это упростит структуру метода - он будет проще восприниматься
  246.                  */
  247.                   ...
  248. ****************************
  249.  public static ExpectedCondition<WebElement> listElementHasExactText(final By elementsLocator, final String expectedText) {
  250.         if (expectedText == "") {
  251.             throw new IllegalArgumentException("expected texts is empty.");
  252.         }
  253.         /*
  254.             тут - точно такой проверки делать не стоит
  255.             вполне может быть - что нам надо найти элемент с пустым текстом
  256.             это вполне штатная ситуация
  257.  
  258.             в texts  и подобных кондишенах
  259.             мы проверяя что передали хоть сколько-то текстов -
  260.             страховали себя от использования кондишена - когда ему на вход не передано ни одного текста
  261.             да, ты придумала, как это использовать в своих целях)
  262.             но в общем - странный способ проверки текстов - при условии что текстов вообще не передали
  263.             с решением по texts и exactTexts и exactTextsInVisibleElements я с тобой согласилась - там
  264.             возвращать проверку количества текстов не надо
  265.  
  266.             просто объясняю разницу между этой ситуацией
  267.             и ситуацией в texts и exactTexts и exactTextsInVisibleElements
  268.  
  269.         */
  270.         ...
  271.             public String toString() {
  272.                 return String.format("\n locator %s\n should contain exact text: %s\n while actual texts are: \n%s ",
  273.                         elementsLocator, expectedText, actualTexts);
  274.             }
  275.         /*
  276.             фраза странная )
  277.             корректнее - что-то вот такое
  278.  
  279.             element of list found by locator ....
  280.             should have exact text ...
  281.             while actual texts are
  282.         */
  283. ******************************************
  284.         public static ExpectedCondition<WebElement> listElementContainsClass(final By elementsLocator, final String expectedClassName) {
  285.                 if (expectedClassName == "") {
  286.                     throw new IllegalArgumentException("expected texts is empty.");
  287.                 }
  288.                 /*
  289.                     то же самое про проверку
  290.                     тут она не нужна
  291.                     да и фраза про ошибку не соотвествовала действительности
  292.  
  293.                     эти мелочи могут в итоге сильно испортить жизнь
  294.                     потом сообщения про ошибки - толком ничего не дадут для понимания - что же у нас
  295.                     пошло не так
  296.                 */
  297.  
  298.                ...
  299.                         actualTexts = getTexts(elements);
  300.                         for (int i = 0; i < actualTexts.size(); i++) {
  301.                             if (actualTexts.get(i).getClass().toString().contains(expectedClassName)) {
  302.                         /*
  303.                             мы уже обсуждали это с тобой
  304.                             да и в listVisibleElementContainsClass ты применила правильные приемы
  305.  
  306.                             actualTexts.get(i) - это строка
  307.                             actualTexts.get(i).getClass() - это класс String
  308.                             нам разве это нужно для анализа?
  309.  
  310.                             такой кондишен тебе не нужен)
  311.                             смело прибивай его
  312.                         */
  313. *****************************
  314.    public static ExpectedCondition<WebElement> listVisibleElementContainsClass(final By elementsLocator, final String expectedClassName) {
  315.         if (expectedClassName == "") {
  316.             throw new IllegalArgumentException("expected texts is empty.");
  317.         }
  318.         /*
  319.             эта проверка - не нужна
  320.             мотивы - такие же, как описывала выше
  321.  
  322.             что касается имени и сути реализации
  323.             вспомни вариант селенидовский
  324.             разве мы фильтровали список тасок по visible перед тем как искать таску с классом editing?
  325.             мы просто в списке искали элемент с нужным нам классом
  326.             да и здесь ты также искала)
  327.             просто имя кондишена - не точное
  328.  
  329.             переименуй кондишен
  330.             с listVisibleElementContainsClass
  331.             на listElementHasCssClass
  332.  
  333.             а параметр expectedClassName
  334.             на expectedCssClass / expectedCssClassName
  335.         */
  336.         return elementExceptionsCatcher(new ExpectedCondition<WebElement>() {
  337.             private List<String> actualClasses;
  338.             private List<WebElement> elements;
  339.             /*
  340.                этот список - нужен только внутри apply
  341.                вот там его и стоит объявить
  342.             */
  343.  
  344.             public WebElement apply(WebDriver driver) {
  345.                 elements = driver.findElements(elementsLocator);
  346.                 actualClasses = new ArrayList<String>();
  347.                 int j = 0;
  348.                 /*
  349.                     а нужна эта переменная?
  350.                 */
  351.  
  352.                 for (WebElement element : elements) {
  353.                     String actualClass = element.getAttribute("class");
  354.                     actualClasses.add(actualClass);
  355.                     /*
  356.                         можно переписать в одну строку
  357.                         actualClasses.add(element.getAttribute("class"));
  358.                       */
  359.                 }
  360.  
  361.    ...
  362.             public String toString() {
  363.                 return String.format("\n element of list found by locator %s\n should contain exact class: %s\n while actual calsses are: \n%s ",
  364.                         elementsLocator, expectedClassName, actualClasses);
  365.             }
  366.       /*
  367.         should contain exact class -> should have cssClass
  368.         while actual calsses are -> while actual elements classes are
  369.       */
  370. ************************************************
  371. public static ExpectedCondition<WebElement> exactTextOf(final By elementLocator, final String expectedText) {
  372.         if (expectedText == "") {
  373.             throw new IllegalArgumentException("expected texts is empty.");
  374.         }
  375.         /*
  376.             проверка не нужна - те же причины, что выше описывала
  377.  
  378.             логика имени кондишена
  379.  
  380.             если у нас texts и exactTexts и exactTextsInVisibleElements
  381.             то разумнее не exactTextOf, а exactText
  382.             чтоб уже единообразно
  383.         */
  384.         return elementExceptionsCatcher(new ExpectedCondition<WebElement>() {
  385.  
  386.             private String actualText;
  387.             private WebElement element;
  388.             /*
  389.                 element используется только в apply -
  390.                 там его и объявляй
  391.             */
  392.  
  393.             public WebElement apply(WebDriver driver) {
  394.                 element = driver.findElement(elementLocator);
  395.                 actualText = element.getText();
  396.  
  397.                 if (actualText.equals(expectedText)) {
  398.                     return element;
  399.                 }
  400.                 return null;
  401.                 /*
  402.                     вот это - можно переписать
  403.                     return (actualText.equals(expectedText)) ? element : null;
  404.  
  405.                     гугли ternary operator java
  406.                 */
  407.             }
  408.  
  409.             public String toString() {
  410.                 return String.format("\n locator %s\n should contain exact text: %s\n while actual text is: \n%s ",
  411.                         elementLocator, expectedText, actualText);
  412.             }
  413.             /*
  414.                 element found by locator ...
  415.                 should have exact text ...
  416.                 while actual text is ...
  417.             */
  418.         });
  419.     }
  420. **********************************************
  421. $(By.id("new-todo")).clear();
  422. $(By.id("new-todo")).sendKeys(taskText, Keys.ENTER);
  423.  
  424. /*
  425.     реализуй в ConciseAPI метод setValue(WebElement element, ....)
  426.     (какой тип у второго параметра - посмотри на сигнатуру sendKeys)
  427.     в котором для элемента вызовешь clear() и sendKeys(...)
  428.  
  429.     чтобы использовать его как  setValue($(By.id("new-todo")), taskText, Keys.ENTER)
  430. */
  431. ************************************
  432.     public static void hover(WebElement element) {
  433.         Actions action = new Actions(getDriver());
  434.         action.moveToElement(element).perform();
  435.     }
  436.  
  437.     ...
  438.  
  439.     public static void doubleClick(WebElement element) {
  440.             Actions action = new Actions(getDriver());
  441.             action.doubleClick(element).perform();
  442.     }
  443. /*
  444.     методы - универсальные
  445.     переноси их в ConciseAPI
  446.  
  447.     можешь кстати реализовать  Actions actions()
  448.     возвращающий new Actions(getDriver())
  449.  
  450.     и тут его применять
  451.     в обоих методах
  452. */
  453. *******************************
  454. public static By tasks = By.cssSelector("#todo-list li");
  455. ...
  456.  public static void assertTasks(String... tasksTexts) {
  457.         $$(By.id("todo-list li")).contains(tasksTexts);
  458.  }
  459. /*
  460.     у нас уже есть переменная tasks
  461.  
  462.     да и вариант By.id("todo-list li") - не рабочий
  463.     т к id = todo-list, li - ни при чем к id
  464.  
  465.     что касается кода $$(...).contains(...);
  466.     такой код - делает вот что
  467.     у нас есть список List<WebElement> - получили в результате $$(...)
  468.     и теперь метод contains списка  - проверяет - есть ли в списке єлементі, равніе тому, что мі передали в contains
  469.     и вернет такая проверка boolean-значение - да или нет
  470.  
  471.     в нашем случае - вернет нет
  472.     т к среди вебэлементов точно нету массива строк)
  473.  
  474.     что в тесте есть проверка
  475.     в случае прохождения проверки - тест работает дальше
  476.     иначе - он должен упасть
  477.  
  478.     именно так работает assertThat
  479.     и ему на вход - надо дать кондишен
  480.     он у тебя тоже есть) - exactTexts
  481.  
  482. */
  483. *****************************
  484.     public static void assertVisibleTasks(String... tasksTexts) {
  485.         $$(exactTextsInVisibleElements(tasks, tasksTexts));
  486.     }
  487.  
  488.     public static void assertNoTasks() {
  489.         assertThat(isNoElements(By.cssSelector("#todo-list li")));
  490.     }
  491.  
  492.     public static void assertNoVisibleTasks() {
  493.         assertThat(isNoVisibleElements(By.cssSelector("#todo-list li")));
  494.     }
  495. /*
  496.     а вот тут уже ок assertThat применяешь
  497.     не забывай про переменную  By tasks = By.cssSelector("#todo-list li");
  498.     используй ее
  499.     не надо в коде заново писать By.cssSelector("#todo-list li")
  500.     это не DRY
  501. */
  502. ***********************************
  503.  public static WebElement startEdit(String oldTaskText, String newTaskText) {
  504.         ...
  505.         WebElement element = ....
  506.         element.clear();
  507.         element.sendKeys(newTaskText);
  508.         return element;
  509.  }
  510. /*
  511.     тут тоже тебе пригодится метод setValue (если делала все по ревью - он уже в ConciseAPI есть у тебя)
  512. */
  513. ********************************
  514.  public static void ensureSiteOpened(Filter filter) {
  515.         if (!(url().equals(filter.toString()))) {
  516.             open(filter.toString());
  517.         }
  518.         $(newTask).isDisplayed();
  519.         /*
  520.             $(newTask) - уже ждем видимости
  521.             isDisplayed() - возвращаем да/нет
  522.  
  523.             у нас было в селенидовской версии - мы ждали enabled
  524.  
  525.             в селениуме есть подобный кондишен elementToBeClickable
  526.             https://seleniumhq.github.io/selenium/docs/api/java/org/openqa/selenium/support/ui/ExpectedConditions.html#elementToBeClickable-org.openqa.selenium.By-
  527.  
  528.             тут будет assertThat для элемента с локатором newTask и нужного кондишена
  529.         */
  530.  ***************************************
  531.   public static <T> T executeJavaScript(String jsCode, Object... arguments) {
  532.          return (T) ((JavascriptExecutor) getDriver()).executeScript(jsCode, arguments);
  533.   }
  534. /*
  535.     перенеси метод в ConciseAPI
  536. */
  537. ***************************************
  538. public class TodoMvc extends ConciseAPI {
  539. ...
  540. public class BaseTest extends ConciseAPI {
  541. /*
  542.     а это ты не с того бренча подсмотрела)
  543.     вспомни - как мы уже в прошлой работе реализовали
  544.     https://bitbucket.org/OlyaP/modularsimple/src/ef4316c6648e?at=modularsimple
  545.  
  546.     мы не наследовали пейджей и тест-классы от ConciseAPI
  547.     ConciseAPI = просто контейнер статических полезных методов и хранилище для вебдрайвера
  548. */
  549. ****************************************
  550.     public static final String URL = "https://todomvc4tasj.herokuapp.com/";///
  551.     /*
  552.         урл прописан в пейдже
  553.         не надо дублировать его и здесь, в BaseTest
  554.  
  555.         кроме того - хорошо бы оставить BaseTest универсальным, непривязанным к нюансам приложения
  556.         вот в прошлой работе - идеальный универсальный BaseTest
  557.     */
  558.     @BeforeClass
  559.     public static void configTimeout() {
  560.         Configuration.timeout = 15;
  561.         setDriver(new FirefoxDriver());
  562.     }
  563.     /*
  564.         начнем с того, что для todoMVC не нужен такой таймаут
  565.         да и если бы и был нужен - вспомни - где это делать грамотнее
  566.         явно не в  BaseTest
  567.  
  568.         имя метода - не отражает  того что он делает
  569.  
  570.         а как перенесешь/уберешь Configuration.timeout = 15; - так и вообще не будет отражать)
  571.     */
  572.  
  573.  ************************
  574.   @Test
  575.      public void testEditCancelAtAll() {
  576.          given(All_FILTER);
  577.          add("a");
  578.          filterAll();
  579. /*
  580.     не понятно)
  581.     почему не given(All_FILTER, "a");
  582.  
  583.     для чего тогда с гивенами заводились)
  584. */
  585. ****************************
  586.   @Test
  587.     public void testEditAtActive() {
  588.         givenAtActive(aTask(TaskType.ACTIVE, "b"));
  589.         filterActive();
  590. /*
  591.     тут тоже самое)
  592.     givenAtActive - уже мы на Active
  593. */
Advertisement
Add Comment
Please, Sign In to add comment