Как я скажу Графене загрузить мою @Page?

TL;DR: Как мне сообщить Graphene, какой (относительный) URL-адрес загружать для объекта, введенного @Page?


Я пытаюсь настроить свои интеграционные тесты веб-интерфейса, используя "современное состояние", а именно сочетание Arquillian, Arquillian Drone, Selenium 2 и Graphene 2.

С Arquillian, Drone и простым Selenium WebDriver (т.е. без каких-либо специфических графеновых компонентов) тест может выглядеть следующим образом:

import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.arquillian.container.test.api.RunAsClient;
import org.jboss.arquillian.drone.api.annotation.Drone;
import org.jboss.arquillian.junit.Arquillian;
import org.jboss.arquillian.test.api.ArquillianResource;

import org.jboss.shrinkwrap.api.spec.WebArchive;
import org.jboss.shrinkwrap.resolver.api.maven.Maven;

import org.junit.Assert;
import org.junit.Test;

import org.junit.runner.RunWith;

import org.openqa.selenium.WebDriver;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@RunWith(Arquillian.class)
public class LoginIT {
    private static final Logger LOG = LoggerFactory.getLogger(LoginIT.class);

    @Deployment
    public static WebArchive createDeployment() {

        return Maven.resolver().loadPomFromFile("pom.xml")
                    .resolve("de.zalando:purchasing-frontend-general:war:?")
                    .withoutTransitivity().asSingle(WebArchive.class);
    }

    @Drone
    WebDriver driver;

    @ArquillianResource
    URL deploymentUrl;

    @Test
    @RunAsClient
    public void testLoginPage() {
        LOG.info("executing test!");

        driver.get(deploymentUrl + "");

        final String title = driver.getTitle();
        LOG.info("title: " + title);
        Assert.assertEquals("Login page title is wrong",
                            "Zalando General Purchasing – Login", title);
    }
}

(Мне потребовалось некоторое время, чтобы получить правильное развертывание из-за устаревшей документации для ShrinkWrap.)

Этот простой тест просто проверяет, перенаправлены ли мы с домашней страницы на страницу входа и правильно ли ее название. Оно работает.

Graphene 2 добавляет новую важную функцию, "автоматическую разводку" абстракций страницы. Тогда мой тест может выглядеть так (без импорта и части развертывания, как указано выше):

@RunWith(Arquillian.class)
public class LoginIT {
    private static final Logger LOG = LoggerFactory.getLogger(LoginIT.class);

    @Deployment
    public static WebArchive createDeployment() {
        // as above
    }

    @Page
    LoginPage loginPage;


    @Test
    @RunAsClient
    public void testLoginPage() {
        String title = loginPage.getTitle();
        LOG.info("title: " + title);
        Assert.assertEquals("Login page title is wrong",
                            "Zalando General Purchasing – Login", title);
    }
}

Используя этот объект "Абстракция страницы":

import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;

public class LoginPage {

    @FindBy(tagName = "title")
    private WebElement titleElement;

    public String getTitle() {
        return titleElement.getText();
    }
}

Это на самом деле работает, мой тест не проваливается и даже выводит правильный заголовок. Но это не работает вообще (я не знаю, почему я, кажется, думал, что это работает, я должен был посмотреть на результаты предыдущего теста) ...

Я получаю "org.openqa.selenium.NoSuchElementException: не удается найти элемент с именем: заголовок" с очень длинной трассировкой стека (через все Arquillian, Graphene, Java Reflection API, плагин Maven Surefire и две строки моего кода).

Отладка в методе показывает, что он, наконец, пытается получить доступ к Html-элементу, а под рукой находится HtmlPage about:blankстраница, а не моя страница входа.

Это как это должно работать? И почему это не работает для меня?

Затем я хочу протестировать другие страницы, кроме страницы входа, и для этого мне нужно использовать другие стартовые URL.

С простым Drone+ Selenium Webdriver я бы просто использовал

driver.get(deploymentUrl + "/otherPage");

в качестве первой строки теста. Но что делать с графеновой 2-страничной аннотацией?

Как мне сообщить Graphene, какой URL (по отношению к deployUrl) загружать для объекта, внедренного в @Page?

2 ответа

Поведение ожидается. Графен инициализирует поля Page Objects.

Для автоматической загрузки страницы вы можете инкапсулировать местоположение объекта страницы в @Location аннотаций. Вместе с @InitialPageВы можете достичь желаемого поведения.

Ваше объявление объекта страницы будет выглядеть так:

import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import import org.jboss.arquillian.graphene.page.Location;

@Location("login.html")
public class LoginPage {

    @FindBy(tagName = "title")
    private WebElement titleElement;

    public String getTitle() {
        return titleElement.getText();
    }
}

Ваш тест:

@Test
@RunAsClient
public void testLoginPage(@InitialPage LoginPage loginPage) {
    String title = loginPage.getTitle();
    LOG.info("title: " + title);
    Assert.assertEquals("Login page title is wrong",
                        "Zalando General Purchasing – Login", title);
}

Теперь login.html будет загружен автоматически относительно вашего contextRoot как первое действие во время выполнения теста. Вы можете прочитать больше об этой функции в документации.

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

public interface AbstractPage {

    public abstract String getURL();
}

@RunWith(Arquillian.class)
public abstract class AbstractWebDriverTest<P extends AbstractPage> {

    @Page
    private P page;

    @Before
    public void goToUrl() {
        driver.get(deploymentURL + page.getURL());
    }
}

Затем каждый тестовый класс собирается реализовать AbstractPage со страницей, указанной в <>, Взгляните на этот пример проекта, надеюсь, это поможет!

Другие вопросы по тегам