gpt4 book ai didi

java - 如何实现可以返回不同 PageObjects 的 WebDriver PageObject 方法

转载 作者:搜寻专家 更新时间:2023-10-30 19:42:50 25 4
gpt4 key购买 nike

我刚开始使用 WebDriver ,我正在尝试学习最佳实践,特别是使用 PageObjectsPageFactory .

我的理解是PageObjects应该暴露网页上的各种操作,并将WebDriver代码与测试类隔离开来。很多时候,相同的操作可能会导致导航到不同的页面,具体取决于所使用的数据。

例如,在这个假设的登录场景中,提供管理员凭据会将您带到 AdminWelcome 页面,而提供客户凭据会将您带到 CustomerWelcome 页面。

所以最简单的实现方法是公开两个返回不同页面对象的方法...

登录页面对象

package example;

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

public class Login {

@FindBy(id = "username")
private WebElement username;

@FindBy(id = "password")
private WebElement password;

@FindBy(id = "submitButton")
private WebElement submitButton;

private WebDriver driver;

public Login(WebDriver driver){
this.driver = driver;
}

public AdminWelcome loginAsAdmin(String user, String pw){
username.sendKeys(user);
password.sendKeys(pw);
submitButton.click();
return PageFactory.initElements(driver, AdminWelcome.class);
}

public CustomerWelcome loginAsCustomer(String user, String pw){
username.sendKeys(user);
password.sendKeys(pw);
submitButton.click();
return PageFactory.initElements(driver, CustomerWelcome.class);
}

}

并在测试类中执行以下操作:

Login loginPage = PageFactory.initElements(driver, Login.class);
AdminWelcome adminWelcome = loginPage.loginAsAdmin("admin", "admin");

Login loginPage = PageFactory.initElements(driver, Login.class);
CustomerWelcome customerWelcome = loginPage.loginAsCustomer("joe", "smith");

替代方法

我希望有一种更简洁的方法来公开返回相关 PageObject 的单个 login() 方法,而不是重复代码。

我考虑过创建一个页面层次结构(或让它们实现一个接口(interface)),以便我可以将其用作返回类型,但感觉很笨拙。我想出的是以下内容:

public <T> T login(String user, String pw, Class<T> expectedPage){
username.sendKeys(user);
password.sendKeys(pw);
submitButton.click();
return PageFactory.initElements(driver, expectedPage);
}

这意味着您可以在测试类中执行以下操作:

Login loginPage = PageFactory.initElements(driver, Login.class);
AdminWelcome adminWelcome =
loginPage.login("admin", "admin", AdminWelcome.class);

Login loginPage = PageFactory.initElements(driver, Login.class);
CustomerWelcome customerWelcome =
loginPage.login("joe", "smith", CustomerWelcome.class);

这很灵活 - 您可以添加一个 ExpiredPassword 页面,而不必更改 login() 方法 - 只需添加另一个测试并传入适当的过期凭据和 ExpiredPassword 页面作为预期的页面。

当然,您可以很容易地离开 loginAsAdmin()loginAsCustomer() 方法,并用对通用 login() 的调用替换它们的内容 (然后将其设为私有(private))。一个新页面(例如 ExpiredPassword 页面)将需要另一个方法(例如 loginWithExpiredPassword())。

这样做的好处是方法名称实际上是有意义的(您可以很容易地看到登录有 3 种可能的结果),PageObject 的 API 更容易使用(没有“预期页面”可以传入),但 WebDriver 代码仍在被重用。

进一步改进...

如果您确实公开了单个 login() 方法,则可以通过向这些页面添加标记界面来使登录可以访问哪些页面变得更加明显(这可能不是必需的,如果你为每个场景公开一个方法)。

public interface LoginResult {}

public class AdminWelcome implements LoginResult {...}

public class CustomerWelcome implements LoginResult {...}

并将登录方法更新为:

public <T extends LoginResult> T login(String user, String pw, 
Class<T> expectedPage){
username.sendKeys(user);
password.sendKeys(pw);
submitButton.click();
return PageFactory.initElements(driver, expectedPage);
}

这两种方法似乎都很有效,但我不确定它如何扩展以适应更复杂的场景。我还没有看到任何类似的代码示例,所以我想知道当页面上的操作会根据数据产生不同的结果时,其他人会怎么做?

或者只是复制 WebDriver 代码并为数据/PageObjects 的每个排列公开许多不同的方法是常见的做法吗?

最佳答案

Bohemian 的回答不灵活——你不能让一个页面操作返回到同一个页面(比如输入错误的密码),你也不能有超过 1 个页面操作导致不同的页面(想想你有多乱) d 如果登录页面有另一个导致不同结果的操作)。您最终还会堆放更多的 PageObjects 来满足不同的结果。

在进一步尝试之后(包括登录失败的情况),我确定了以下几点:

private <T> T login(String user, String pw, Class<T> expectedPage){
username.sendKeys(user);
password.sendKeys(pw);
submitButton.click();
return PageFactory.initElements(driver, expectedPage);
}

public AdminWelcome loginAsAdmin(String user, String pw){
return login(user, pw, AdminWelcome.class);
}

public CustomerWelcome loginAsCustomer(String user, String pw){
return login(user, pw, CustomerWelcome.class);
}

public Login loginWithBadCredentials(String user, String pw){
return login(user, pw, Login.class);
}

这意味着你可以重用登录逻辑,但是阻止了测试类在预期页面中传递的需要,这意味着测试类的可读性非常强:

Login login = PageFactory.initElements(driver, Login.class);
login = login.loginWithBadCredentials("bad", "credentials");
// TODO assert login failure message
CustomerWelcome customerWelcome = login.loginAsCustomer("joe", "smith");
// TODO do customer things

为每个场景使用单独的方法也使 Login PageObject 的 API 非常清晰 - 并且很容易告诉登录的所有结果。我没有看到使用接口(interface)的任何值(value)限制使用 login() 方法的页面。

我同意 Tom Anderson 的观点,即可重用的 WebDriver 代码应该重构为细粒度的方法。它们是细粒度公开(以便测试类可以选择相关操作),还是组合并作为单个粗粒度方法公开给测试类,这可能取决于个人喜好。

关于java - 如何实现可以返回不同 PageObjects 的 WebDriver PageObject 方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13371699/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com