Есть отличная удаленная работа для php+codeception+jenkins+allure+docker спецов. 100% remote! Присоединиться к проекту

Как правильно построить архитектуру - много шопов, локаторы разные

architecture
selenium
webdriver
Теги: #<Tag:0x00007f7b6d6a88e0> #<Tag:0x00007f7b6d6a87a0> #<Tag:0x00007f7b6d6a83e0>

(vlogvinov) #1

Здравствуйте!

Столкнулся стакой ситуацией - есть написаный фреймворк(или лучше даже назваить refapp) для ссоздание интеренет-магазинов. На этом рефапе создано много различных магазинов. Функциональность этих шопов где-то процентов на 70 одинаковая, а вот локаторы, в большинстве случаев, отличаються.

Первичная задача - автоматизировать смоук тесты…

Вопросы:

  1. Лучше под каждый отдельный шоп писать всё или можно это каким-либо образом красиво организовать?

  2. Если возможно организовать, то как?

Что пытался сделать:

  1. Для каждого шопа создал отдельный конфигурационный xml файл с набором тестов и параметрами(название бренда). Этот параметр передаю в каждом тесте. В методах проверяю какой бренд и если функциональность и локаторы совпадают с refapp, то отрабатывает деволтные методы. Если локаторы/функциональность другая, то пишу отдельно методы для них.

Пример теста:


@Test
    @Parameters({"brand"})
    public void testSuccessfulLogin(String brand) {
        User user = new User()
                .withEmail("emailv@gmail.com")
                .withPassword("12345678");
        app.getUserHelper().login(brand, user);

С тестом вроде всё хорошо, но сам метод - ужас.

 public void login(String brand, User user) {
        initLogin(brand);
        fillLoginForm(brand, user);
        submitLoginForm(brand);
    }

    private void submitLoginForm(String brand) {
        if (brand.equals("shop1") || brand.equals("shop2") || brand.equals("shop3") || brand.equals("shop4") || brand.equals("shop5")) {
            click(By.cssSelector("button[name=rm_login_login]"));
        }
    }


    private void initLogin(String brand) {
        if (brand.equals("shop1")) {
            click(By.cssSelector("div .b-login_dropdown > span"));
        } else if (brand.equals("shop2")) {
            hoverOnElement(driver.findElement(By.cssSelector("span.b-login_dropdown-title.js-login_dropdown-title")));
            click(By.cssSelector("div.b-login-tooltip"));
        } else if (brand.equals("shop3")) {
            hoverOnElement(driver.findElement(By.cssSelector("div.b-login_wide")));
        } else if (brand.equals("shop4")) {
            hoverOnElement(driver.findElement(By.cssSelector("span.b-login_dropdown-title.js-login_dropdown-title")));
        } else if (brand.equals("sho5")) {
            hoverOnElement(driver.findElement(By.cssSelector("div.b-login_wide.js-login_dropdown")));
        }
    }

Подскажите, пожалуйста, как рерали такую задачу, если у кого-то есть подобный опыт. И возможно ли вообще делать как в примере выше.

Спасибо


(Sergey Pirogov) #2

If поможет убрать паттерн стратегия


(Дмитрий Мирошник) #3

Я бы использовал PageObject с дополнительной прослойкой Shop между Page и имплементацией.

abstract class Page (…) {

}

abstract class Shop (Page) {
int shopID
}

class LoginPage (Shop) {
void LoginPage (shopID){
webElement loginButton = readProperty (propFile, “loginButton” + IntToStr (this.shopID))

}
}

А в тесте это будет выглядеть так:

private void initLogin {
loginPage = new LoginPage (shopID); // shopID приходит в класс теста снаружи
loginPage.loginButton.click();
}

Для локаторов используется внешний файл, в котором локаторы будут храниться в виде
loginButton1 div .b-login_dropdown > span
loginButton2 span.b-login_dropdown-title.js-login_dropdown-title
Ну и т.д.
Тут много чего не хватает, но я надеюсь, идея понятна :slight_smile:


(Vladislav Kulasov) #4

Как то странно. У вас конечные локаторы отличаются, скорей всего. Возможно у вас, на пример, используются одинаковые кнопки (одинаковая структура), но внутри разные ID. Это не значит, что совсем локаторы разные.
На пример то что у вас, можно с помощью xpath //[starts-with(@class,‘b-login_’)]
берите элемент выше например //div[@name=‘button’]/descendant::
[starts-with(@class,‘b-login_’)]
Можно что то общее найти и к нему привязаться


(Alexander Zvonov) #5

Следует создать некую абстракциюю Вынести однотипную логику в абстрактный клас либо использовать интерфейсы, а потом расширять\оверрайдить логику в конкретных реализациях.( разные магазины) Стратегия, как было сказано выше близка, к тому что вам нужно, но не факт что красиво ляжет. нужно разбираться
Суть в том, что вам нужно отделить вещи которые изменяются от неизменных.