Каким образом описать класс с множеством однотипных элементов

Каким образом описать класс с множеством однотипных элементов?
Вот скажем есть у меня меню со множеством пунктов и подпунктов, каким образом мне описать это дерево?

если делать так:

    @Block(@FindBy(className = "af_table_data-body"))
    public class FormularsTree extends HtmlElement {

        @FindBy(xpath = "//div[.='Формуляры']/span[@class='af_treeTable_icon-container']/a")
        public WebElement formularUNFASpan;

        @FindBy(xpath = "//div[.='Поступление НФА']/span[@class='af_treeTable_icon-container']/a")
        public WebElement releaseUNFASpan;

        @FindBy(xpath = "//span[@class='bpmenu_font_color' and text()='Приходный ордер на приемку МЦ']")
        public WebElement creditOrderMCLink;

        @FindBy(xpath = "//span[@class='bpmenu_font_color' and text()='Акт о приеме-передаче объектов нефинансовых активов (ф. 0504101)']")
        public WebElement actOfReceptionAndTransmissionFacilities;

то каждый пункт описывать это громоздко

Вот в этом я и вижу минус “классической” модели Page Object, в которой все элементы описываются как поля класса.

А не надо их описывать как поля класса.
Сделайте в пэдж-обжекте один метод вместо кучи полей:

public WebElement getByText(String text) {
  return webdriver.find(By.xpath("//span[@class='bpmenu_font_color' and text()='" + text + "']");
}
5 лайков

Я бы вам посоветовал попробовать наш опенсорс фреймворк JDI
Подобные элементы можно записать так:

@FindBy(xpath = "//div[*[@class='af_treeTable_icon-container']]")
public Tabs formularUNFASpan;
@FindBy(css = ".bpmenu_font_color")
public Tabs creditOrderMCLink;

Использовать так:

formularUNFASpan.select("Формуляры");
creditOrderMCLink.select("Акт о приеме-передаче объектов нефинансовых активов (ф. 0504101)")

Dependency:

<dependency>
    <groupId>com.epam.jdi</groupId>
    <artifactId>jdi-uitest-web</artifactId>
    <version>1.0.1-SNAPSHOT</version>
</dependency>

Код проекта:

1 лайк

Идея просто отличная! ) Спасибо.
Сейчас прикручу и попробую.

А где документация? Как оно работает

Я на проектах давно пользуюсь таким подходом, работает без каких либо вопросов

что-то он не скачал депенденси) пишет что не нашел)

вот дока

Пока документация есть в файле там же в Гит в корне файл “JDI UI TEST Framework Docs.docx”
А также в виде примеров использования там же пакеты
jdi-uitest-tutorialtests - большой пример тестового сценария
и
jdi-uitest-webtests - много маленьких тестов на методы-примеры
jdi-uitest-webtests
Мы сейчас работаем над сайтом и большим количеством примеров так что если заинтересовало следите за обновлениями )
там еще много других прикольных фишек, по элементам есть спец пейджобджекты для форм и большой класс таблиц с кучей действий над ними.
К примеру форму можно объявить так:

public LoginForm extends Form<User> {
    @FindBy(className = loginName)    private TextField name;
    @FindBy(className = password)      private TextField password;
    @FindBy(className = rememberme) private Checkbox rememberMe;
    @FindBy(className = loginbutton)    private Button loginButton;
}

@FindBy(id = loginForm) 
public static LoginForm loginForm;
  • больше никакого кода!
    Использовать можно так:


    loginForm.login(new User(“user”, “P@ssw0rd”)); - заполняет форму и нажимает кнопку loginButton
    loginForm.submit(new User(“user”, “P@ssw0rd”)); - тоже самое
    loginForm.fill(User.AdminUser); - только заполняет форму
    Map<String, String> userPairs = new HashMap();
    userPairs.put(“name”, “user”);
    userPairs.put(“password”, “P@ssw0rd”);
    loginForm.verify(userPairs) - проверяет заполнены ли поля формы в соответствии с Map

    Причем локаторы у всех элементов будут включать родительский (его можно не указывать)
    т.е. допустим локатор для loginButton будет равен
    css = #loginForm .loginButton
    и так для всех элементов

  • во всех методах можно использовать как объект, так и Map. название поля в User должно совпадать с названием поля в LoginForm т.е.

    public class User {
    private String name
    private String password;
    }
    Завтра приду на работу, скину сюда презенташку ) А подробнее будет большая презентация на SQA Days

1 лайк

Наверно версия 1.0.1 еще не опубликовалась в Maven Central (можно попробовать 1.0.0). Но он точно есть в sonatype
Добавьте в pom такую запись и должно заработать

<repositories>
        <repository>
            <id>oss-sonatype</id>
            <name>oss-sonatype</name>
            <url>https://oss.sonatype.org/content/repositories/snapshots/</url>
            <snapshots>
                <enabled>true</enabled>
                <updatePolicy>always</updatePolicy>
            </snapshots>
        </repository>
    </repositories>

см. пример в gga-selenium-framework/pom.xml at master · ggasoftware/gga-selenium-framework · GitHub

1 лайк

Ждем :wink:

Вот ссылки на google disk )
https://drive.google.com/file/d/0B958oJxLdPHgWmhidno3UkxzQUU/view - последняя внутренняя презентация для Инженеров (Январь 2016)
https://drive.google.com/file/d/0B958oJxLdPHgaU40UWJlNjNqSms/view - старая внутренняя презентация для Инженеров (Сентябрь 2015)
https://drive.google.com/file/d/0B958oJxLdPHgVkM2Q3IxRDg5Ync/view - (бизнес презентация) новая презентация для Менеджеров/Клиента (Февраль 2016)

Enjoy )))
P.S. Также мы планируем выступить на SQA Days и QA Conference этой весной :slight_smile:

2 лайка

Здравствуйте Андрей! я в проект хочу продвинуть selenide+cucumber+allure/serenity с возможностью запуска из Selenium Grid`a и развёртывании из Docker.

Но вопрос не по этой теме - можно ли использовать “классическую” модель Page Object вместе с динамическим локатором, как Вы показали в выше в примере. Хотелось бы использовать “классическую” модель, а где нельзя - то динамический XPATH.

@iljapavlovs Да, можно и нужно.
Вот здесь есть несколько примеров, как можно делать такие и такие пэдж объекты: google/test/org/selenide/examples/google at main · selenide-examples/google · GitHub

ищешь @FindBy корневой елемент, а от него просто через .findElement по тексту другие span-и или div -и

Из примера про page object в ситиле Selenide:

$(By.name("q")).val(text).pressEnter();

что доллар означает - обозначение вебэлемента?
val - записать значение в этот вебэлемент (если это input или textarea), а почему у него есть метод pressEnter? это методы нажатия на клавиатуру?

читается пока не очень очевидно, по крайней мере мне

мне кажеться кирилицу в локатори лупить как то не гуманно)) лучше попросить UI-щиков какой data attribute добавить или как то так…

@Viktor_Borisov
Да, $ - это вебэлемент. val - установка значения в поле, pressEnter - нажать enter.
Как пишется, так и читается - один-в-один.

Ну, это же обычное дело: ставишь курсор в поле (того же самого гугла), вводишь пару букв и нажимаешь ввод. Я даже маму научил так делать. :slight_smile:

Ну, не более неочевидно, чем любой пример на любом другом незнакомом языке/фреймворке. :slight_smile:

В данном случае синтаксис 100% узнаваем для всех, кто хоть как-то сталкивался с веб-разработкой (JQuery). Если же $ и val дико не нравятся, есть и более длинный, но типа человекочитаемые аналоги:

getElement(By.name(“q”)).setValue(text).pressEnter();

1 лайк

Спасибо) думаю возможно стоит ознакомиться.

Добрый день, какие преимущества у Вашей системы если сравнивать ее, к примеру, с Serenity?