【问题标题】:How do I tell Graphene to load my @Page?我如何告诉 Graphene 加载我的@Page?
【发布时间】:2013-07-23 13:47:54
【问题描述】:

TL;DR:我如何告诉 Graphene 为 @Page 注入的对象加载哪个(相对)URL?


我正在尝试使用“最先进的技术”设置我的 Web 前端集成测试,即 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 增加了一个重要的新功能,"autowiring" Page abstractions。然后我的测试可能看起来像这样(省略上面的导入和部署部分):

@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: Unable to locate element with name: title”和一个非常长的堆栈跟踪(通过所有 Arquillian、Graphene、Java Reflection API、Maven Surefire 插件和两行我的代码)。

对该方法的调试表明它最终尝试访问 Html-Element,而手头的 HtmlPage 是about:blank-page,而不是我的登录页面。

它应该是这样工作的吗? 为什么它对我不起作用?

然后我想测试登录页面以外的其他页面,为此我需要使用其他起始 URL。

使用普通的 Drone+ Selenium Webdriver,我会简单地使用

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

作为测试的第一行。但是如何处理 Graphene 2 @Page-Annotation?

如何告诉 Graphene 为 @Page 注入的对象加载哪个 URL(相对于 deploymentUrl)?

【问题讨论】:

    标签: java selenium-webdriver jboss-arquillian graphene2 arquillian-drone


    【解决方案1】:

    这种行为是预期的。 Graphene 初始化 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 自动加载,作为测试执行期间的第一个操作。 您可以在documentation 阅读有关此功能的更多信息。

    【讨论】:

      【解决方案2】:

      我个人使用继承和泛型来实现这一点(但它可能不是最好的解决方案)。您可以查看例如here。您需要像这样定义 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());
          }
      }
      

      然后每个测试类将使用&lt;&gt; 中指定的页面实现AbstractPage。看看那个示例项目,希望对您有所帮助!

      【讨论】:

      • 那么goToUrl会在从@Page注解填充页面之前执行?但是在页面对象创建之后呢?我无法理解这一点,但会尝试一下。
      • 这取决于,@Before 将在测试之前执行(所以是的 - 在加载页面对象之前),@After 当然是之后:) 另外请注意,页面对象是延迟加载的,石墨烯试图在失败之前加载 WebElements 几次。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-11-24
      • 2017-12-26
      • 1970-01-01
      • 2020-05-10
      • 2016-12-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多