使用 JAVA 数组或列表填充由 Selenium 页面对象模型设计的页面上的文本框
Using JAVA array or list to fill text boxes on a page designed by Selenium Page Object Model
package com.objects;
import java.util.ArrayList;
import java.util.List;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.How;
import org.openqa.selenium.support.PageFactory;
import com.tests.BaseClass;
public class LinkedInHomePage extends BaseClass {
public LinkedInHomePage(WebDriver driver) {
PageFactory.initElements(driver, this);
}
@FindBy(how = How.ID, using = "firstName-coldRegistrationForm")
public WebElement newFirstNameTexthBox;
@FindBy(how = How.NAME, using = "lastName")
public WebElement newLastNameTexthBox;
@FindBy(how = How.ID, using = "email-coldRegistrationForm")
public WebElement newEmailTexthBox;
@FindBy(how = How.ID, using = "password-coldRegistrationForm")
public WebElement newPasswordTexthBox;
@FindBy(how = How.ID, using = "btn-submit")
public WebElement signUpButton;
public void EnterNewFirstName(String inComingNewFirstName) {
newFirstNameTexthBox.clear();
newFirstNameTexthBox.sendKeys(inComingNewFirstName);
}
public void EnterNewLastName(String inComingNewLastName) {
newLastNameTexthBox.clear();
newLastNameTexthBox.sendKeys(inComingNewLastName);
}
public void EnterNewEmail(String inComingNewEmail) {
newEmailTexthBox.clear();
newEmailTexthBox.sendKeys(inComingNewEmail);
}
public void EnterNewPassword(String inComingNewPassword) {
newPasswordTexthBox.clear();
newPasswordTexthBox.sendKeys(inComingNewPassword);
}
public void ClickSignUp() {
signUpButton.click();
}
public void JoinNow(String FName, String LName, String Email,
String Password) {
EnterNewFirstName(FName);
EnterNewLastName(LName);
EnterNewEmail(Email);
EnterNewPassword(Password);
ClickSignUp();
}
}
如您所见,上面的 JoinNow() 函数采用多个参数,并且运行良好。我想使用数组或列表来减少
参数的数量,然后使用循环来填充文本框。我想完成类似下面的事情,但是因为我使用的是页面对象模型设计,所以不能使用 findElement。
@SuppressWarnings("unchecked")
protected void JoinNow(String... var) {
List<MyElements> inputElements = new ArrayList<MyElements>();
inputElements.add((MyElements) driver.findElement(By
.id("firstName-coldRegistrationForm")));
inputElements.add((MyElements) driver.findElement(By.id("lastName")));
inputElements.add((MyElements) driver.findElement(By
.id("email-coldRegistrationForm")));
inputElements.add((MyElements) driver.findElement(By
.id("password-coldRegistrationForm")));
for (int i = 0; i < var.length; i++) {
((WebElement) inputElements.get(i)).sendKeys(var[i]);
}
}
在创建页面对象模型时,您需要考虑几个事项。根据您的操作方式(通过使用@FindBy),有时您最终会得到陈旧的数据。为了获得更好的结果,您应该像下面这样定义您的 ID,并使用它们来获取您的 Webelement。这就是我设计它的方式。定义所有 By.id 并将其放入列表中,然后使用下面的函数对其进行简化。
定义者:
static final By FNAME_REGFORM_BY_ID = By.id("firstName-coldRegistrationForm");
public void fillTextBoxes(List<By> bys, List<String> valuesToPopulate) {
List<WebElement> webelements = new ChromeDriver().findElements(By.cssSelector("input[type=text]"));
for (int i = 0; i < bys.size(); i++) {
new ChromeDriver().findElement(bys.get(i)).sendKeys(valuesToPopulate.get(i));
}
}
编辑:为了更好地理解,fillTextBoxes 等同于 joinNow。
List<String> values=new LiskedList<String>();
Values.add("emailid");
values.add("firstname");
List<By> bys=new LinkedList<By>();
bys.add(FNAME_REGFORM_BY_ID);
bys.add(EMAIL_ID_By_ID);
public void joinNow(List<By> bys, List<String> values) {
List<WebElement> webelements = new ChromeDriver().findElements(By.cssSelector("input[type=text]"));
for (int i = 0; i < bys.size(); i++) {
new ChromeDriver().findElement(bys.get(i)).sendKeys(valuesToPopulate.get(i));
}
}
不要使用带注释的@FindBy(how = How.ID, using = "email-coldRegistrationForm") 等,因为这会减慢执行速度并为您提供陈旧的数据。 FindBy 往往会变慢,因为整个页面对象只有在所有元素都可用后才会完全初始化。像我提到的那样尝试使用 Static By。我们 运行 遇到性能问题并开始从带注释的 Findby 切换。
根据要求,这里有一个示例实现。您可能需要根据您的项目要求进行调整,但这应该开始了。
您的页面 Class(为了我的缘故重命名为 SO)。
public class SO {
WebDriver driver;
static final By FNAME_REGFORM_BY_ID = By.id("firstName-coldRegistrationForm");
static final By LNAME_REGFORM_BY_NAME = By.className("lastName");
static final By EMAIL_REGFORM_BY_ID = By.id("email-coldRegistrationForm");
static final By PWD_REGFORM_BY_ID = By.id("password-coldRegistrationForm");
static final By SUBMIT_REGFORM_BY_ID = By.id("btn-submit");
public SO(WebDriver driver) {
this.driver = driver;
}
public List<By> getAllInput() {
List<By> bys = new LinkedList<By>();
bys.add(FNAME_REGFORM_BY_ID);
bys.add(LNAME_REGFORM_BY_NAME);
bys.add(LNAME_REGFORM_BY_NAME);
bys.add(LNAME_REGFORM_BY_NAME);
bys.add(LNAME_REGFORM_BY_NAME);
return bys;
}
public void joinNow(List<String> values) {
PageFactory.initElements(this.driver, HotelDetailsPage.class);
List<By> bys = this.getAllInput();
List<WebElement> webElements = this.driver.findElements(By.cssSelector("input[type=text]"));
for (int i = 0; i < bys.size(); i++) {
new ChromeDriver().findElement(bys.get(i)).sendKeys(values.get(i));
}
}
public SO open(final String url) {
this.driver.get(url);
return this;
}
}
测试方法:
@Test
public void testForm() {
WebDriver driver = new FirefoxDriver();
SO so = new SO(driver);
SO soPage = so.open("your app url");
List<String> values = new LinkedList<String>();
values.add("firstname");
values.add("lastName");
values.add("emailId");
values.add("password");
values.add("id");
soPage.joinNow(values);
}
为什么不发送 Map
到 JoinNow
方法。我建议您保持 PageObject 模式不变。我相信这在长期内更具可读性和可维护性
Map<String,String> data = new HashMap<String,String>();
data.put("firstname", "George");
data.put("lastname", "Clooney");
data.put("email", "George@xyz.com");
data.put("password", "Dontguess");
JoinNow(data);
protected void JoinNow(Map<String,String> data) {
firstNameElement.sendKeys(data.get("firstname"));
lastNameElement.sendKeys(data.get("lastname"));
emailElement.sendKeys(data.get("email"));
passwordElement.sendKeys(data.get("password"));
}
另一种方式如下:
HashMap<WebElement, String> d = new HashMap<WebElement, String>();
d.put(newFirstNameTexthBox, "Michael");
d.put(newLastNameTexthBox, "Johnson");
d.put(newEmailTexthBox, "a@b.com");
d.put(newPasswordTexthBox, "Michael123$");
joinNow(d);
protected void JoinNow(Map<WebElement,String> data) {
for (Entry<WebElement, String> objValue : data.entrySet())
objValue.getKey().sendKeys(objValue.getValue());
}
package com.objects;
import java.util.ArrayList;
import java.util.List;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.How;
import org.openqa.selenium.support.PageFactory;
import com.tests.BaseClass;
public class LinkedInHomePage extends BaseClass {
public LinkedInHomePage(WebDriver driver) {
PageFactory.initElements(driver, this);
}
@FindBy(how = How.ID, using = "firstName-coldRegistrationForm")
public WebElement newFirstNameTexthBox;
@FindBy(how = How.NAME, using = "lastName")
public WebElement newLastNameTexthBox;
@FindBy(how = How.ID, using = "email-coldRegistrationForm")
public WebElement newEmailTexthBox;
@FindBy(how = How.ID, using = "password-coldRegistrationForm")
public WebElement newPasswordTexthBox;
@FindBy(how = How.ID, using = "btn-submit")
public WebElement signUpButton;
public void EnterNewFirstName(String inComingNewFirstName) {
newFirstNameTexthBox.clear();
newFirstNameTexthBox.sendKeys(inComingNewFirstName);
}
public void EnterNewLastName(String inComingNewLastName) {
newLastNameTexthBox.clear();
newLastNameTexthBox.sendKeys(inComingNewLastName);
}
public void EnterNewEmail(String inComingNewEmail) {
newEmailTexthBox.clear();
newEmailTexthBox.sendKeys(inComingNewEmail);
}
public void EnterNewPassword(String inComingNewPassword) {
newPasswordTexthBox.clear();
newPasswordTexthBox.sendKeys(inComingNewPassword);
}
public void ClickSignUp() {
signUpButton.click();
}
public void JoinNow(String FName, String LName, String Email,
String Password) {
EnterNewFirstName(FName);
EnterNewLastName(LName);
EnterNewEmail(Email);
EnterNewPassword(Password);
ClickSignUp();
}
}
如您所见,上面的 JoinNow() 函数采用多个参数,并且运行良好。我想使用数组或列表来减少 参数的数量,然后使用循环来填充文本框。我想完成类似下面的事情,但是因为我使用的是页面对象模型设计,所以不能使用 findElement。
@SuppressWarnings("unchecked")
protected void JoinNow(String... var) {
List<MyElements> inputElements = new ArrayList<MyElements>();
inputElements.add((MyElements) driver.findElement(By
.id("firstName-coldRegistrationForm")));
inputElements.add((MyElements) driver.findElement(By.id("lastName")));
inputElements.add((MyElements) driver.findElement(By
.id("email-coldRegistrationForm")));
inputElements.add((MyElements) driver.findElement(By
.id("password-coldRegistrationForm")));
for (int i = 0; i < var.length; i++) {
((WebElement) inputElements.get(i)).sendKeys(var[i]);
}
}
在创建页面对象模型时,您需要考虑几个事项。根据您的操作方式(通过使用@FindBy),有时您最终会得到陈旧的数据。为了获得更好的结果,您应该像下面这样定义您的 ID,并使用它们来获取您的 Webelement。这就是我设计它的方式。定义所有 By.id 并将其放入列表中,然后使用下面的函数对其进行简化。
定义者:
static final By FNAME_REGFORM_BY_ID = By.id("firstName-coldRegistrationForm");
public void fillTextBoxes(List<By> bys, List<String> valuesToPopulate) {
List<WebElement> webelements = new ChromeDriver().findElements(By.cssSelector("input[type=text]"));
for (int i = 0; i < bys.size(); i++) {
new ChromeDriver().findElement(bys.get(i)).sendKeys(valuesToPopulate.get(i));
}
}
编辑:为了更好地理解,fillTextBoxes 等同于 joinNow。
List<String> values=new LiskedList<String>();
Values.add("emailid");
values.add("firstname");
List<By> bys=new LinkedList<By>();
bys.add(FNAME_REGFORM_BY_ID);
bys.add(EMAIL_ID_By_ID);
public void joinNow(List<By> bys, List<String> values) {
List<WebElement> webelements = new ChromeDriver().findElements(By.cssSelector("input[type=text]"));
for (int i = 0; i < bys.size(); i++) {
new ChromeDriver().findElement(bys.get(i)).sendKeys(valuesToPopulate.get(i));
}
}
不要使用带注释的@FindBy(how = How.ID, using = "email-coldRegistrationForm") 等,因为这会减慢执行速度并为您提供陈旧的数据。 FindBy 往往会变慢,因为整个页面对象只有在所有元素都可用后才会完全初始化。像我提到的那样尝试使用 Static By。我们 运行 遇到性能问题并开始从带注释的 Findby 切换。
根据要求,这里有一个示例实现。您可能需要根据您的项目要求进行调整,但这应该开始了。
您的页面 Class(为了我的缘故重命名为 SO)。
public class SO {
WebDriver driver;
static final By FNAME_REGFORM_BY_ID = By.id("firstName-coldRegistrationForm");
static final By LNAME_REGFORM_BY_NAME = By.className("lastName");
static final By EMAIL_REGFORM_BY_ID = By.id("email-coldRegistrationForm");
static final By PWD_REGFORM_BY_ID = By.id("password-coldRegistrationForm");
static final By SUBMIT_REGFORM_BY_ID = By.id("btn-submit");
public SO(WebDriver driver) {
this.driver = driver;
}
public List<By> getAllInput() {
List<By> bys = new LinkedList<By>();
bys.add(FNAME_REGFORM_BY_ID);
bys.add(LNAME_REGFORM_BY_NAME);
bys.add(LNAME_REGFORM_BY_NAME);
bys.add(LNAME_REGFORM_BY_NAME);
bys.add(LNAME_REGFORM_BY_NAME);
return bys;
}
public void joinNow(List<String> values) {
PageFactory.initElements(this.driver, HotelDetailsPage.class);
List<By> bys = this.getAllInput();
List<WebElement> webElements = this.driver.findElements(By.cssSelector("input[type=text]"));
for (int i = 0; i < bys.size(); i++) {
new ChromeDriver().findElement(bys.get(i)).sendKeys(values.get(i));
}
}
public SO open(final String url) {
this.driver.get(url);
return this;
}
}
测试方法:
@Test
public void testForm() {
WebDriver driver = new FirefoxDriver();
SO so = new SO(driver);
SO soPage = so.open("your app url");
List<String> values = new LinkedList<String>();
values.add("firstname");
values.add("lastName");
values.add("emailId");
values.add("password");
values.add("id");
soPage.joinNow(values);
}
为什么不发送 Map
到 JoinNow
方法。我建议您保持 PageObject 模式不变。我相信这在长期内更具可读性和可维护性
Map<String,String> data = new HashMap<String,String>();
data.put("firstname", "George");
data.put("lastname", "Clooney");
data.put("email", "George@xyz.com");
data.put("password", "Dontguess");
JoinNow(data);
protected void JoinNow(Map<String,String> data) {
firstNameElement.sendKeys(data.get("firstname"));
lastNameElement.sendKeys(data.get("lastname"));
emailElement.sendKeys(data.get("email"));
passwordElement.sendKeys(data.get("password"));
}
另一种方式如下:
HashMap<WebElement, String> d = new HashMap<WebElement, String>();
d.put(newFirstNameTexthBox, "Michael");
d.put(newLastNameTexthBox, "Johnson");
d.put(newEmailTexthBox, "a@b.com");
d.put(newPasswordTexthBox, "Michael123$");
joinNow(d);
protected void JoinNow(Map<WebElement,String> data) {
for (Entry<WebElement, String> objValue : data.entrySet())
objValue.getKey().sendKeys(objValue.getValue());
}