Selenium中的页面对象模型最佳实践

时间:2011-11-03 15:51:20

标签: java object selenium webdriver pageobjects

在对页面对象进行建模时,如何处理具有表单的页面和大约50个输入字段?这里的最佳做法是什么?

您是否会为每个输入操作创建一个页面对象并编写一个单独的函数?或者你会写一个函数,哪些参数传递给它并输入文本?

e.g。

public void enterFirstName(String firstName) {
    driver.type("firstNameField", firstName);
}

public void enterSecondName(String secondName) {
    driver.type("secondNameField", secondName);
}

public void fillInForm(String inputFieldName, String text) {
    driver.type(inputFieldName, text);
}

我可以在第一个模型中看到,在编写测试时,测试更具描述性,但如果页面包含太多输入字段,则创建页面对象会变得很麻烦。

这篇文章在构建页面对象中的selenium测试时也非常有趣 Functional Automated Testing Best Practices with Selenium WebDriver

6 个答案:

答案 0 :(得分:10)

页面对象模型背后的想法是它将实现从呼叫者抽象出来。在第一种机制中,您成功地执行了此操作,因为调用者不需要知道html输入字段名称是否从“firstName”更改为“user_first_name”,而在第二种实现中,对实际页面的任何更改都必须是传递给页面对象的所有调用者。

虽然创建页面对象可能需要更多的工作,但如果你保持封装,那么当真正的html页面不可避免地发生变化时,它将长期保存工作。

答案 1 :(得分:9)

我总是喜欢把事情分解成一组相关的信息。例如,如果我有一个用户类,我可能会将其分解为几个较小的类:LoginCredentials,ProfileInfo,Settings等,但我通常仍然会有一个包含这些子类的顶级User类。

我肯定会建议将一个对象传递给一个FillForm函数而不是所有这些函数。使用这种方法有一些很大的优势。一,您可以使用一些“常见”预配置对象,用于许多测试用例。例如:

public class FormInfo
{
   string Domain;
   string Name;
   string Category;
   // etc...

  public FormInfo(string domain, string name, string category)
  {
     Domain = domain;
     Name = name;
     Category = category;
     // etc...
  }
}


// Somewhere in your initialization code
public static FormInfo Info1 = new FormInfo("myDomain1", "myName1", "myCategory1");
public static FormInfo Info2 = new FormInfo("myDomain2", "myName2", "myCategory2");

You can still update one of your common merchants if you need to do something one-off:

// In your test case:
Info1.Category = "blah";
FormPage.FillForm(Info1);

或者,您可以根据需要为特定测试用例创建全新的商家对象。您也可以使用这些对象执行字段验证之类的操作,或者我通常做的是打破特定字段验证的页面对象模式,因此如果我验证商家域字段,我可能会这样做:

Info1.Domain = null; //This should make the FillForm function skip doing anything with this field.
FormPage.FillForm(Info1);
FormPage.DomainTextBox.Text = "field validation string";

这种方法的另一个重要优点是,如果页面被更新以添加,删除或修改字段,您只需要更新FormInfo对象和FillForm函数,而不需要修改调用它的特定测试用例。 FillForm函数 - 假设它们正在使用您常用的FormInfo对象之一。获得更多覆盖的另一种可能性是设置一个常见的FormInfo对象,为每个符合最小/最大长度的字段生成随机字符串,并在所有不同的允许字符之间循环。这允许您从同一组测试中获得一些额外的测试,但如果您开始仅从特定字符串获得失败结果,它也可能会添加一些噪音,所以要小心。

答案 2 :(得分:1)

除了enterWhatever()方法之外,我通常还会创建一个createWhatever(field1, field2, ...)方法,我可以将其用作创建任何表单构建的快速路径,以便在 real <时使用/ strong>测试的目的是另外的。因此,如果我需要创建一个Customer来测试提交Ticket,那么测试将转到CreateACustomer页面并调用createCustomer(firstName, lastName, emailAddress, ...),然后继续执行创建一个更细致的任务使用该客户的票证。

答案 3 :(得分:1)

为了读者的利益,我正在回答一个老问题。

除了这里的其他好答案之外,我想在这里为那些刚接触POM的人添加一些建议。

页面对象是众所周知的设计模式,被自动化工程师广泛接受,为应用程序的每个页面创建单独的类文件,以将所有元素作为属性及其行为/业务功能分组为类的方法。但是在为页面创建类时几乎没有问题 - 特别是当页面具有更多/不同的元素集/复杂元素(如网格/日历小部件/ HTML表等)时。

该类可能包含太多不能处理的职责。它应该重组并分成更小的类。即,遵循 Single Responsibility Responsible

点击此处查看图片。

enter image description here

即创建可重用的页面片段&amp;让主页面对象提供页面片段。

查看here了解详情。

答案 4 :(得分:0)

我在表单中执行此操作的方法是获取页面上所有输入的列表。然后删除任何未显示的输入元素。之后,我可以为每个输入添加有效或无效的文本。从那里我抓住验证摘要,以确保我得到正确的错误。如果没有,则记录异常。

这样做是允许我将文本输入到页面上的输入数量,它仍然允许我记录异常并通过电子邮件发送。我还在列表中捕获textareas和密码字段,并且我有一个单独的复选框字段和选项列表,因为我通常想要对这些字段做些不同的事情。

归结为我需要做的就是测试一个页面:

for (int i = 0; i < inputs.Count(); i++)
{
  //This captures the error message string created in the input validation method
  //nextButton is the IWebElement of the button to click to submit the form for validation
  //ErrorMessageID is the ID of the Validation Summary display box (i.e. ErrorMessageID = "FormSummary" <asp:ValidationSummary ID="FormSummary" runat="server" CssClass="errorMessage" />

  string InputValidationText = utilities.InputValidation(driver, inputs, i, nextButton, ErrorMessageID)
  if(InputValidationText != string.Empty)
  {
    //LogError
  }
}

答案 5 :(得分:0)