Як "перескакувати" між PageObjects в Selenide

Хай всім.
Почав освоювати технологію Selenide (тому не судіть строго:). І майже зразу ж зіштовхнувся з однією проблемою.

Як, прекондишн, зробив логування:

    public static void openBrowser(String serverUrl) {
        baseUrl = serverUrl;
        timeout = 10000;
        startMaximized = true;
        clearBrowserCache();
        open(baseUrl + "/login.jsp");
        login();
    }

Потім, в тестових класах, щоб оминути непотрібні степи, в @BeforeClass перевідкриваю потрібну для тестування сторінку:

    @BeforeClass
    public void openTable() {
        page(baseUrl + "/some.jsp?param1=" + var1 + "&param2=" + var2);
        //open() теж пробував
    }

Ну і далі, собсна, тести…
От тільки прогін фейлиться зразу ж після виконання openBrowser() з NPE (не може зайти з PageObject).

скиньте код повністю. з цих кусків не видно ні пейджобжекта ні тестів

**

PageObject:

**

public class TablePage {

    public void runTableAction(String nameOfItemInList) {
        $(By.className("gwt-toolbar-icon-table-action")).click();
        $(byText(nameOfItemInList)).click();
    }

    public void markActionAsTrueForSpecifiedRow(int row){
        final int ACTION_COLUMN_INDEX = 1;
        SelenideElement actionElement = $(By.xpath(cellLocatorGenerator(row, ACTION_COLUMN_INDEX)));
        if (actionElement.is(disabled)){
            actionElement.click();
        }
    }

    private String cellLocatorGenerator(int row, int column) {
        return "//tr[" + row + "]/td[" + column + "]";
    }
}

**

TestClass:

**

public class TestDBETable extends TestBase{
    TablePage tablePage;
    TableActionsInputParametersCRM inputParameters;

    @BeforeClass
    public void openTable() {
        page(baseUrl + "/dbe.jsp?warehouseId=" + getWarehouseIdCRM() + "&tableId=757");
        $(withText("Accounts")).shouldBe(visible);
    }

    @Test(groups = "AddAccountToWorklist")
    public void testAddAccountToWorklist(){
        tablePage.markActionAsTrueForSpecifiedRow(2);
        tablePage.runTableAction("Add Accounts");
        inputParameters.fillAddAccountToWorklistInputs("2017-02-08", "2017-02-20", "Some SUBJ");
        tablePage.getPopUpMessage()
                .shouldHave(Condition.text(SUCCESS_TABLE_ACTION_RESULT_MESSAGE));
    }

page -> tablePage
звідки береться тейблПейдж?

Оголосив змінну для класу TablePage щоб використовувати його методи.
Думаю, можливо методи TablePage зробити статичними?

Скиньте повний стектрейс звідки саме вилітає NPE. З коду підозрюю що tablePage непроініціалізована.

1 лайк

tablePage = startPage.doSomeThing();
об’єкт цієї сторінки повинен звідкись взятися. на гітхабі є навчальний проект, він простий і відкритий. Подивіться як будується pageObject, і як його використовують тести

Може бути. Справа в тому, що я не докінця розумію як ініціалізація PageObject(а) проходить в Selenide.

В проекті Selenium. А я використовую Selenide. Як це реалізується в Selenium я знаю. Дякую :slight_smile:

ну ок

Знову ж таки - без стектрейсу це вгадування.
Спробуйте так:

@BeforeClass
    public void openTable() {
        open(baseUrl + "/dbe.jsp?warehouseId=" + getWarehouseIdCRM() + "&tableId=757");
        $(withText("Accounts")).shouldBe(visible);
        tablePage = new TablePage(); //або tablePage = page(TablePage.class); - метод page мабуть є сенс використовувати тільки коли самі PageObjects в стилі PageFactory (з філдами - вебелементами), без цього виконається той самий new TablePage() тільки через reflection
    }

Вот заметка, о том какие проблемы возникают при использовании PageFactory в Selenide Automation Remarks

Вывод - лучше инициализировать обьекты явно и будет счастье

1 лайк

Зробив наступним чином:

    TablePage tablePage = page(TablePage.class);
    TableActionsInputParametersCRM inputParameters;
    @BeforeClass
    public void openTable() {
        open(baseUrl + "/dbe.jsp?warehouseId=" + getWarehouseIdCRM() + "&tableId=757");
        $(withText("Accounts")).shouldBe(visible);
    }

І зловив наступний ексепшн:

org.testng.TestNGException: 
Cannot instantiate class com.logivations.w2mo.ui.crm.dbe.tableactions.crm.TestDBETableActionsAccountsTable
	at org.testng.internal.ObjectFactoryImpl.newInstance(ObjectFactoryImpl.java:40)
	at org.testng.internal.ClassHelper.createInstance1(ClassHelper.java:377)
	at org.testng.internal.ClassHelper.createInstance(ClassHelper.java:290)
	at org.testng.internal.ClassImpl.getDefaultInstance(ClassImpl.java:125)
	at org.testng.internal.ClassImpl.getInstances(ClassImpl.java:190)
	at org.testng.internal.TestNGClassFinder.<init>(TestNGClassFinder.java:130)
	at org.testng.TestRunner.initMethods(TestRunner.java:424)
	at org.testng.TestRunner.init(TestRunner.java:247)
	at org.testng.TestRunner.init(TestRunner.java:217)
	at org.testng.TestRunner.<init>(TestRunner.java:161)
	at org.testng.SuiteRunner$DefaultTestRunnerFactory.newTestRunner(SuiteRunner.java:556)
	at org.testng.SuiteRunner.init(SuiteRunner.java:168)
	at org.testng.SuiteRunner.<init>(SuiteRunner.java:117)
	at org.testng.TestNG.createSuiteRunner(TestNG.java:1319)
	at org.testng.TestNG.createSuiteRunners(TestNG.java:1306)
	at org.testng.TestNG.runSuitesLocally(TestNG.java:1160)
	at org.testng.TestNG.run(TestNG.java:1064)
	at org.testng.IDEARemoteTestNG.run(IDEARemoteTestNG.java:72)
	at org.testng.RemoteTestNGStarter.main(RemoteTestNGStarter.java:127)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:497)
	at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
Caused by: java.lang.reflect.InvocationTargetException
	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
	at java.lang.reflect.Constructor.newInstance(Constructor.java:422)
	at org.testng.internal.ObjectFactoryImpl.newInstance(ObjectFactoryImpl.java:29)
	... 23 more
Caused by: java.lang.RuntimeException: Failed to create new instance of class com.logivations.w2mo.ui.pages.dbe.tables.TablePage
	at com.codeborne.selenide.Selenide.page(Selenide.java:562)
	at com.logivations.w2mo.ui.crm.dbe.tableactions.crm.TestDBETableActionsAccountsTable.<init>(TestDBETableActionsAccountsTable.java:20)
	... 28 more
Caused by: java.lang.InstantiationException
	at sun.reflect.InstantiationExceptionConstructorAccessorImpl.newInstance(InstantiationExceptionConstructorAccessorImpl.java:48)
	at java.lang.reflect.Constructor.newInstance(Constructor.java:422)
	at com.codeborne.selenide.Selenide.page(Selenide.java:560)
	... 29 more

А що получається у випадку TablePage tablePage = new TablePage(); ?

1 лайк

TablePage tablePage = page(TablePage.class);

Инициализацию внеси в BeforeClass
чтоб вышло

 @BeforeClass
    public void openTable() {
        open(baseUrl + "/dbe.jsp?warehouseId=" + getWarehouseIdCRM() + "&tableId=757");
        $(withText("Accounts")).shouldBe(visible);
        tablePage = new TablePage ();
    }

Как помню у тестНГ по особенному инициализируются объекты

1 лайк

Ага. Дійсно допомогло. Дякую. Також дякую @dshy. Створив SelenidePageFactory :wink:

Але зараз маю наступну траблу. open() в @BeforeClass не запускається і видає NoSuchElementException:

Element not found {with text: Accounts}
Expected: visible

Але то скоріше за все проблема не то з wait-ами, не то з timeout-ами… Бо при debug все “фуркає” :slight_smile:

    private TablePage tablePage;

    @BeforeClass
    public void openTable(){
        tablePage = new TablePage ();
        open(baseUrl + "/dbe.jsp?warehouseId=" + getWarehouseIdCRM() + "&tableId=757");
        $(withText("Accounts")).shouldBe(visible);
    }

Ну это значит, что у тебя нет элемента на странице с текстом Accounts, может по другому попробуешь поискать?

И не стоит писать проевор в прекондишонах, хотя дело вкуса в целом. Но если у тебя для тест сценария откроется не нужная страница, то тест в любом случае упадёт. Но при этом упадёт тест, а не прекондишн

Тут не в тому справа. Метод open(...) не спрацьовує. Тобто сторінка не відкривається і тому NoSuchElementException і вилітає. При дебагу, все ок.

  1. в метод open() можно не указывать baseUrl, Селенид автоматически подставляет значение baseUrl если в метод передаётся значение не начинающееся с https|http|file…
  2. Что выполняется getWarehouseIdCRM() может не корректное значение возвращается?
  3. Попробуй аннотировать класс с тестом @Listeners({GlobalTextReport.class}). Увидишь какой урл открывается
  4. Выложи ка сюда stacktrace того, что отображается в логе