julia_v_iluhina

Untitled

Oct 27th, 2016
92
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 19.12 KB | None | 0 0
  1. http://joxi.ru/DrlQ5oLh4WnbMm
  2. /*
  3.     заботься о форматировании кода
  4.     пропуск одной строки - разумно использовать для форматирования
  5.     а пропуск нескольких строк к ряду - уже лишнее
  6.     https://google.github.io/styleguide/javaguide.html#s4.6.1-vertical-whitespace
  7.  
  8.     пропуск строки снутри методов используешь по-разному
  9.     иногда - первую строку пропускаешь
  10.     иногда - нет
  11.  
  12.     я бы придерживалась какого-то одного правила
  13.     например, если метод одно-двустрочный - не делать пропусков строк внутри метода
  14.     а если код в методе надо делить по блокам для более простого понимания
  15.     то и вначале и в конце метода я бы тоже строку пропустила
  16.  
  17.     отступы отлчаются от стандартных
  18.     выдели код
  19.     и с меню code->reformat code
  20.  
  21.     такие действия - стоит делать привычкой
  22.     перед тем, как отдаешь код кому-то или выкладываешь в репозиторий
  23.  
  24.     они простые, не требуют раздумий особых
  25.     а код от этого выглядит нагляднее
  26.  
  27. */
  28. ****************************************
  29. public abstract class ConciseApi {
  30. /*
  31.     класс нужно объявлять абстрактным - если ты планируешь от него что-то наследовать
  32.     и если внутри методов класса ты хочешь оперировать методом, который реализуешь в потомках
  33.     вот такой метод - который у потомков будет по-разному реализован, и который уже на уровне предка
  34.     используется в логике других методов - объявляется в классе-предка как абстрактный класс
  35.  
  36.     в данной версии - этого нету
  37.     ConciseApi - просто класс-контейнер статических методов, полезных нам и в пейджах, и в тест-классах
  38.  
  39.     В следующей версии как раз будет версия, когда ConciseApi будет абстрактным предком для других классов
  40.  
  41.     конечно, можно объявлять класс абстрактным только для того, чтобы показать,
  42.     что объекты такого класса не могут создаваться.
  43.     по моему мнению, в таком случае можно это не уточнять
  44.         раз в классе - все методы статические, я уже понимаю - для чего этот класс
  45.         это класс - контейнер статических методов, и объект такого типа я точно делать не буду
  46.  
  47.         конечно, уточнив, что класс - abstract, создать объект такого типа станет просто невозможным)
  48.         если есть причины об это обеспечить - наверное надо объявлять класс как abstract
  49.  
  50.         вспомни - мы пейджи-модули, или классы-хелперы - не объявляли ведь как abstract
  51.         хотя и подразумевали - что объектов такого класса создавать не будем
  52.  
  53.  
  54.     почитать про абстрактные классы
  55.  
  56.     тут немного сложновато для начала
  57.     http://docs.oracle.com/javase/tutorial/java/IandI/abstract.html
  58.  
  59.     тут примеры простого кода
  60.     http://www.javatpoint.com/abstract-class-in-java
  61.  
  62.     тоже неплохо - пример и объяснения
  63.     http://tutorials.jenkov.com/java/abstract-classes.html
  64.  
  65.     пример и пошаговые объяснения
  66.     http://crunchify.com/what-is-an-abstract-class-and-abstract-method-in-java-when-should-i-use-it/
  67.  
  68.     теория с примерами
  69.     https://www.tutorialspoint.com/java/java_abstraction.htm
  70.  
  71.     вопрос и ответы, сложновато, но вопрос рассматривается с разных сторон
  72.     http://stackoverflow.com/questions/1320745/abstract-class-in-java
  73.  
  74. */
  75. ************************
  76. http://joxi.ru/v29WjP9hG0QQbr
  77. /*
  78.     а вот кондишену - не нужен параметр - вебдрайвер
  79.  
  80.     1 - параметр не нужен
  81.     2 - т к у метода apply кондишена уже есть такой параметр, нам его будет достаточно
  82. */
  83. ****************************************
  84.  public static ExpectedCondition<Boolean> nthElementHasText(WebDriver driver, final By elementsLocator, final int index, final String text) {
  85.         return new ExpectedCondition<Boolean>() {
  86.             private List<WebElement> elements;
  87.             /*
  88.                 лучше на уровне класса объявлять те переменные, которые нам пригодятся в нескольких методах
  89.                 ты, в общем, так и сделала)
  90.  
  91.                 я предлагаю на уровне  toString -
  92.                 оперировать либо списком строк - фактических текстов элементов вписка
  93.                 либо строкой - фактическим текстом index-ого элемента списка
  94.                 и уже не писать ничего про размер списка и прочие вещи
  95.  
  96.                 в таком случае - на этом уровне нужны переменные либо
  97.                 List<String> actualTexts
  98.                 или
  99.                 String actualText
  100.  
  101.                 в apply - нужно заполнить такую переменную
  102.                 и для простоты понимания - и анализировать ее значение
  103.  
  104.                 а в  toString() - использовать значение такой переменной для построения сообщения
  105.  
  106.                 а List<WebElement> elements - объявлять и использовать только внутри apply
  107.             */
  108.  
  109.             @Override
  110.             public Boolean apply(WebDriver driver) {
  111.                 elements = driver.findElements(elementsLocator);
  112.  
  113.                 if (index < elements.size()) {
  114.                     return elements.get(index).getText().contains(text);
  115.                 } else
  116.                     return false;
  117.                 /*
  118.                     обрати внимание - в if-блоке используешь фигурные скобки,
  119.                     а в else-блоке - не используешь
  120.  
  121.                     согласно conventions - надо использовать даже если у тебя одна строка кода
  122.                     https://google.github.io/styleguide/javaguide.html#s4.1.1-braces-always-used
  123.  
  124.                     но не спеши подправлять код)
  125.                     предлагаю его переписать)
  126.  
  127.                     на самом деле - проверяя index < elements.size()
  128.                     ты пыталась избежать IndexOfBoundsException
  129.                     которое возникает, когда мы пытаемся обратиться к элементу коллекции по индексу за ее границами
  130.  
  131.                     можно поступить по-другому
  132.                     try{
  133.                         actualText = elements.get(index).getText();
  134.                         return actualText.contains(text);
  135.                     } catch (IndexOutOfBoundsException e) {
  136.                         return false;
  137.                     }
  138.  
  139.                     на самом деле, в процессе работы метода apply могут возникать и другие исключения
  140.                     и их тоже нужно ловить и обрабатывать
  141.                     почитай
  142.                     https://docs.google.com/document/d/1BiYTLdypDfucSqiY9isv1HCKKQIxelzqYrN-3Ku1RWM/edit?usp=sharing
  143.                     и примени такое решение
  144.  
  145.                     можно чуть упростить тип параметра этого кетчера
  146.                     вместо
  147.                     Function<? super WebDriver, V> condition
  148.                     применять
  149.                     ExpectedCondition<V> condition
  150.  
  151.                     т к Function<? super WebDriver, V> - это предок для ExpectedCondition<V> condition
  152.  
  153.                     туда же, в кетчер, можно перенести и работу с IndexOutOfBoundsException
  154.  
  155.                     и тогда все кондишены будут без try-catch секций - что проще
  156.                     а логика перехвата исключений - будет отделена в кетчер
  157.                     это позволит при разработке самих кондишенов сосредоточиться на главном - логике проверки
  158.                     да и читать такой код будет проще
  159.  
  160.                 */
  161.             }
  162.  
  163.             @Override
  164.             public String toString() {
  165.                 if (index < elements.size()) {
  166.                     return String.format("\n element with index %s to be: %s, while actual value is: %s", index, text, elements.get(index));
  167.                 } else {
  168.                     return String.format("\n index is: %s, while actual size of elements is: %s", index, elements.size());
  169.                 }
  170.             }
  171.             /*
  172.                 тут, и в других кондишенах строй фразу по некой одной схеме
  173.                 в toString  уже не должно быть накакой логики или получения чего-то из элементов заново
  174.                 тут - оперируем тем, что анализировали в apply
  175.  
  176.                 element foynd by locator ....
  177.                 should contain text ....
  178.                 while actual text is ... (или - while actual texts are ... - если мы собирали список текстов)
  179.             */
  180.         };
  181.     }
  182.     **********************************
  183.     http://joxi.ru/DmBNWL6FNVP1Nm
  184.  
  185.     /*
  186.         вспомни из видео - как работает new WebDriverWait(...).until(...)
  187.         apply кондишена вызывается в цикле - пока не закончится таймаут или проверка не пройдет
  188.  
  189.         потому нам важно именно ВНУТРИ apply - заново получать список элементов
  190.  
  191.         так, как реализовано сейчас - мы не переискиваем список
  192.         и получается - что многократные вызовы apply все равно будут работать с вариантом списка
  193.         который мы получили изначально - а в этом смысла нету
  194.  
  195.         как и ранее писала - советую в apply собрать список текстов элементов
  196.         и затем его анализировать
  197.         и в toString -  именно его и вывести как часть выражения
  198.     */
  199. *****************************************
  200.     public static ExpectedCondition<Boolean> elementsHaveText(final WebDriver driver, final By elementsLocator, final String... texts) {
  201.     /*
  202.         разумнее объявить этот кондишен как ExpectedCondition<List<WebElement>>
  203.         да, мы это в коде не используем
  204.         но потенциально - это полезнее
  205.         т к в таком случае assertThat для кондишена вернет список вебэлементов
  206.         и это может быть полезно
  207.  
  208.         подумай над типами других уже реализованных кондишенов
  209.  
  210.         про имя кондишена
  211.         можно назвать по аналогии с sizeOf - textsOf
  212.     */
  213.          ....
  214.                 @Override
  215.                 public String toString() {
  216.                     if (elements.size() != texts.length) {
  217.                         return String.format("\n total elements value %s, does not match texts value: %s", elements.size(), texts.length);
  218.                     } else {
  219.                         return String.format("\n elements text to be: %s, while actual are %s", texts, elements);
  220.                     }
  221.                 }
  222.     /*
  223.         тут, и далее - используй тот же принцип - выше писала
  224.         никакой логики дополнительной не должно быть
  225.         никаких новых получений данных
  226.         выводим только то, что анализировали
  227.  
  228.         elements of list found by locator ...
  229.         should contain texts ....
  230.         while actual texts are ....
  231.     */
  232. **************************
  233. public class Mails {
  234.     private static By elementsLocator = By.cssSelector("[role ='main'] .zA");
  235.     /*
  236.         эту переменную стоит назвать в терминах нашего пейджа
  237.         mails - будет ок
  238.         а то, что это именно локатор - будет понятно по типу переменной
  239.     */
  240. ***************************
  241.     @Step
  242.     public void assertMail(int index, String mailTitleText) {
  243.         assertThat(driver, CustomConditions.nthElementHasText(driver, elementsLocator, index, mailTitleText));
  244.     }
  245. /*
  246.     используй import static для CustomConditions.nthElementHasText
  247.     и тогда в коде сможешь использовать nthElementHasText
  248.  
  249.     касается использования любых кондишенов
  250.  
  251.     как использовать  import static - до некоторой степени субъективно)
  252.  
  253.         я придерживаюсь такого принципа
  254.  
  255.         если слово слишком распространенное и/или контекст вызова не помогает это понять -
  256.         то уточняю до имени класса
  257.         или - если решили все статические методы этого класса вызывать указывая имя класса
  258.         (как мы про пейджи решили для Gmail)
  259.         иначе - использую import static
  260.  
  261.         так - например -
  262.         в селениде проектах - использовав кондишены empty / visible - мы использовали import static и не уточнялись
  263.         до имени класса - т к и так все понятно из контекста
  264.         несмотря на то - что сами термины empty / visible используются в разных классах -
  265.         мы могли себе позволить не уточняться до класса - т к контекст вызова все объяснял
  266.  
  267.         а вот By.name(...), String.join(... - я бы уточнялась до класса - т к по одному имени метода непонятно -
  268.         что за зверь
  269.         и тот, кто код читает - будет вынужден посмотреть - что мы там наимпортили
  270. */
  271. *************************
  272. public class BaseTest {
  273.     protected static WebDriver driver;
  274.  
  275.     @BeforeClass
  276.     public static void setup() {
  277.         Configuration.timeout = 6;
  278.         driver = new ChromeDriver();
  279.     }
  280.  
  281.     @AfterClass
  282.     public static void tearDown() {
  283.         driver.quit();
  284.     }
  285.  
  286. }
  287. /*
  288.     реализация предка для тест-класса - ок
  289.  
  290.     реализован он почти универсально
  291.  
  292.     почти - т к установка таймаута портит уиверсальный код
  293.  
  294.     Configuration.timeout = 6; - это уже логика самого тест-класса, а не его предка
  295.     советую перенести это в тест-класс
  296.  
  297.     вспомни - мы для Gmail - когда реализовывали это задание в Selenide - устанавливали таймаут в 15 секунд
  298.     мне вообще приходится устанавливать в 20 )
  299.     возможно  - и тебе таймаута не хватает
  300. */
  301. ************************
  302. public class GmailTest extends BaseTest {
  303.  
  304.     @Test
  305.     public void testLoginSendAndSearch() {
  306.  
  307.         String subject = generateUniqueString("test");
  308.  
  309.         Gmail gmail = new Gmail(driver);
  310.         Mails mails = new Mails(driver);
  311.         Menu menu = new Menu(driver);
  312. /*
  313.     пейджи - лучше обїявляй не в тест-методе
  314.     а на уровне тест-класса
  315.  
  316.     понятно, что в данном случае у нас один тест-метод и технически - без разницы -
  317.     где объявлять пейджи
  318.  
  319.     но - технически -
  320.     в тест-классе - может быть сколь угодно много тест-методов
  321.  
  322.     и они могут появляться постепенно
  323.  
  324.     вот появится второй тест-метод у нас тут
  325.     и нам из-за этого придется менять старый тест-метод
  326.     не очень логично)
  327.  
  328.     а самое главное - все же пейдж = набор инструментов, нужный для конкретного тест-класса
  329.     это именно "собственность"/ответственность/логика тест-класса, а не тест-метода
  330.  
  331.     потому правильнее пейджи объявлять и инициализировать на уровне тест-класса, а не тест-метода
  332. */
Advertisement
Add Comment
Please, Sign In to add comment