如何使用PowerMock在Selenium框架中进行页面对象的单元测试

6
我正在使用基于Page Object设计模式的Selenium 2自动化框架。现在,我想开始考虑为我的代码编写测试套件。由于各种原因,其中一些与效率有关,另一些与我对安装了该框架所测试的Web应用程序的测试环境缺乏所有权和控制有关,我希望避免启动浏览器并使用系统下测试(SUT)来验证我的框架代码。因此,我认为模拟对象是一个不错的替代方案。
问题是,我真的无法理解模拟对象的概念,而且我确实找不到一个像样的具体示例,说明这实际上如何工作。我确实找到了一个似乎很有前途的链接,但是示例实际上太抽象了,对我来说并没有用处。

http://www.methodsandtools.com/archive/testingcodetdd.php

所以,我想发布我的简单LoginPage页面对象,并请求使用PowerMock为此页面对象提供一个或两个单元测试的简单示例。以下是我的LoginPage对象的源代码:

public final class LoginPage extends Page<LoginPage> {

    @FindBy(how = How.ID, using = "username")
    private WebElement usernameBox;

    @FindBy(how = How.ID, using = "password")
    private WebElement passwordBox;

    public LoginPage(final WebDriver driver) {
        this(driver, driver.getCurrentUrl(), DEFAULT_TIMEOUT_IN_SECONDS);
    }

    public LoginPage(final WebDriver driver, final String url) {
        super(driver, url, DEFAULT_TIMEOUT_IN_SECONDS);
    }

    public LoginPage(final WebDriver driver, final String url, final int   
        timeoutInSeconds) {
        super(driver, url, timeoutInSeconds);
    }

    public final void enterUsername(final String username) {
        usernameBox.clear();
        usernameBox.sendKeys(username);
    }

    public final void enterPassword(final String password) {
        passwordBox.clear();
        passwordBox.sendKeys(password);
    }

    public final void clickLoginButton() {
        loginButton.click();
    }

    public final HomePage loginWithGoodCredentials(final User user) {
        return login(user, HomePage.class);
}

    public final LoginPage loginWithBadCredentials(final User user) {
        return login(user, LoginPage.class);
    }

    private <T extends Page<T>> T login(final User user, final Class<T> 
        expectedPage) {

        user.getUsername(), user.getPassword(), user.getType(), expectedPage);
        enterUsername(user.getUsername());
        enterPassword(user.getPassword());
        loginButton.click();

        return Page.constructPage(getDriver(), getTimeoutInSeconds(), 
            expectedPage);
    }

}

我知道模拟WebDriver和WebElement很容易,因为它们是接口,根据我上面发布的链接。但是,我参考的文档并没有很清楚地向完全新手介绍如何使用这些来编写页面对象的单元测试。以公共登录方法为例,这些方法的单元测试看起来像什么?我只需要验证使用登录返回预期类型的页面对象。或者例如,将文本输入到用户名和密码框中的方法...我可能希望有一个测试来验证在输入用户名和密码之前是否擦除了任何现有的文本。由于我没有加载真实应用程序登录页面的真实浏览器,我不确定PowerMock如何实例化和初始化所有我的Web元素以对页面对象的公开服务进行测试。

1
你想测试你代码的哪些方面?在单元测试库中已经进行了单元测试的Web驱动程序代码需要进行单元测试,这对你有什么价值?你能发布一个实际使用该对象的UI/验收测试吗?听起来你只需要在实际测试中验证用户名和密码字段是否被清除或者其他操作。此外,你可以考虑将这个问题迁移到sqa.stackexchange,那里更加偏向于理论QA。 - craastad
我正在考虑删除这个问题。我已经决定不使用PowerMock,而是使用文档非常好的JMockit。另一个选择是编辑问题,询问关于JMockit的内容,并发布自己的答案。目前,我的项目优先级有些变化,单元测试工作被推迟了几周,所以我暂时不能处理这个问题,因为我必须在此时专注于其他事情。 - Selena
2个回答

1

也许http://popperfw.org对你很有趣。它是页面对象模式的一种更加灵活的实现,比起Selenium的默认实现更为出色,并且它直接支持“单元”测试所创建的PageObjects => 它会测试你的PageObjects是否与你测试的页面相匹配。

http://popperfw.org/unitTest.html


这个项目已经停止开发三年了,但它背后的想法看起来不错。你知道有什么替代方案吗? - Rob Audenaerde

-1

Selenium测试不是Mock对象的适当场所。Mock对象用于单元测试具有依赖关系的类。您可以模拟依赖项,以便专注于测试单个类。

Selenium用于基于浏览器的网页/应用程序测试。由于这是一个网页,表明有某种服务器正在运行和运行的浏览器(在Selenium的情况下自动化)。从定义上讲,这是一种集成测试,因为您正在测试最终的“集成”产品。如果出现问题,可能是在ClassA中或者可能是Web服务器配置中。集成测试是发现故障的地方(通常用于减轻QA团队进行回归测试的负担,因为单元测试测试类的功能,而集成测试测试系统作为整体的功能(或者在较小的集成部分中)。

说了这么多,听起来你把两者混淆了。根据您发布的代码,我会说您正在进行集成测试,现在应该忘记Mock对象。


6
我试图独立于它们所代表的网页,单独测试页面对象本身。我在问题中发布的链接中提供了使用另一个框架Mockito的页面对象单元测试的基本示例,而该框架与我最初发问时想使用的框架不同。我已决定使用JMockit而不是Powermock,因为它更简单,文档也更好。最终,我将要么删除这个问题,要么编辑它以询问有关JMockit的问题,并在理解JMockit后发布自己的答案。我并不是第一个询问如何对页面对象进行单元测试的人。 - Selena
好吧,测试的测试?这就是我划定的界限。至于你的问题,我已经广泛使用了Mockito。您可以使用Mockito模拟任何非最终方法/类。不幸的是,对于您的页面设计,您使用了很多最终语句。我建议删除这些语句,以便Mockito可以发挥其作用(如果您没有适当的接口来实现其模拟,则它将子类化您的页面)。 - RockMeetHardplace
9
这并不是“测试测试”。它是我在自动化框架中开发的一个类的测试。该对象支持测试,但本身并不是一个测试。 - Selena
3
我支持塞琳娜的最后一条评论。能够得到一个更好的回答会很不错。 - jumps4fun

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接