如何在此方案中返回WebElement

时间:2015-09-21 08:24:05

标签: java selenium selenium-webdriver webdriver

我想利用页面对象,以下是我正在看的内容:

我创建了一个包' pageObjects'并创建了一个班级' HomePage'使用如下元素:

public class HomePage 
{
    private static WebElement element=null;

    public static WebElement txt_UserName(WebDriver driver)
    {
        element=driver.findElement(By.name("userName"));
        return element;
    }
}

在我的测试用例中,当我使用HomePage.txt_UserName(driver).sendKeys("uday")时 让我们输入用户名为" Uday"。这很完美。

但是我需要在类似的方法中实现 enterValue(" HomePage.txt_UserName""乌代&#34)

public void enterValue(String strObjID,String strValue)
{
  //How should i use the above parameter here?? Something like below should work
  strObjID(driver).sendKeys(strValue);

}

3 个答案:

答案 0 :(得分:1)

根据您的评论,我认为您不应该编写处理所有类型输入字段的通用黄瓜步骤定义。这使得阅读和理解您的功能文件变得非常困难。在HTML中编写HTML ID或CSS选择器不符合BDD,因为您首先编写需求,因此您无法知道正在使用哪些ID。查看principles of BDD

请记住,功能文件的目的是将作为用户故事编写的需求链接到测试代码。因此,请编写您的用户故事等功能文件。例如:

Given I loaded the home page
When I enter my username <username>
And I enter my password <password>
And I press the login in button
Then I should be redirected to <some url>

基于此,您应该彻底实施page object pattern。这是一个例子:

public class HomePage {
    private final WebElement usernameElement;
    // declare more page elements here

    public HomePage(WebDriver driver) {
        usernameElement = driver.findElement(By.name("userName"));
        // init more page elements here
    }

    public void enterUsername(String username) {
        usernameElement.sendKeys(username)
    }

    // more handler here: e.g. public void enterPassword(String password) ...
}

在黄瓜步骤定义中,您可以使用页面对象:

@Then("^I enter my username \"(.+)\"$")
public void I_enter_my_username(String username) {
    homepage.enterUsername(username);
}

此模式可以很好地理解您的功能文件以及它们与测试代码的连接方式。

答案 1 :(得分:0)

请不要制作通用功能。如果您的表单有50个元素,那么无论如何您将不得不处理所有50个元素。更好的做法是将所有代码放在页面对象中而不是测试用例脚本中。您不应要求使用者(脚本编写者)了解页面的HTML。他们应该能够调用一个简单的函数,例如login(username, password) ...而不是enterValue("some crazy XPath", "my name")enterValue("some other crazy XPath", "my password")。稍后出现的人无法分辨出每一行的作用会使调试变得更加困难和耗时。

我同意Schrieveslaach,但我会采取略微不同的方法。我想说你应该将元素捆绑到用户在页面上执行的操作中。例如,使用填写用户名和密码的enterUsername()代替enterPassword()clickLogin()以及login(username, password),然后点击登录按钮。这将简化页面对象的API,并仅公开必要的操作。谁将填写用户名而不是密码?有时您会想要填写某些字段而不是其他字段,可能是负面测试,在这些情况下,您可以为某些字段传入空字符串并完成此操作。

答案 2 :(得分:0)

不要在PageObjects之外处理WebElements或XPath。 pageobject的目的是封装所有页面标识符复杂性并返回用户友好输出。您应该能够调用一个简单的操作,如登录(&#34;用户名&#34;,&#34;密码&#34;),而无需处理Xpath,CSS选择器。

如果您正在寻找包装Selenium的一些更复杂的函数(getDriver等),请使用AbstractPageObject来提供所有PageObjects继承的更多泛型函数,或者在一个公共函数中创建静态函数类。

如果您正在使用pageObject上的大量标识符进行交互,这是不可取的,那么您有几种不同的方法可以解决此问题:

1)将您的页面对象拆分为较小的页面对象

页面对象不必代表单个网页,也不必代表页面上相关元素的集合。您的菜单可以是单个页面对象,也可以是表格。如果您希望表示层次结构,则可以将其作为公共对象包含在父页面上,例如:

public class HomepageObject {

    public MenuPageObject menuPageObject;

    private By element1 = By.id("element-1");
    private By element2 = By.id("element-2");

    public void clickElement1() {
        click(element1);
    }

    ...

}

这样您就可以使用例如:

来访问菜单
 homepage.menuPageObject.clickStuff() 

如果您在许多页面上重复使用元素,那么这样做的另一个好处是,您不必继续包含它们!

2)使您的标识符更通用

或者,您的元素可能类似,您可以通过单个标识符来引用它们。以下代码片段处理可能存在大量共享相似ID的内容的列表。我在这个例子中使用过Java 8流,但如果你觉得它更容易,你可以使用foreach循环。

    private By displayedStuff = By.cssSelector("p[id^='stuff-number-']");

    public Optional<String> getStuff(String stuffText){

         // get a list of the elements
         List<WebElement> stuffList = getDriver().findElements(displayedStuff)

         // return the element text which matches stuffText
         return stuffList.stream()
              .map(e -> e.getText())
              .filter(e -> e.contains(stuffText))
              .findFirst();
    }

你的东西列表可以是任何东西:按钮,表格,下拉列表..如果你有这么多元素,你的页面上可能会有很多重复。除非您的开发人员也手动编码100个独特元素?

3)考虑减少页面上的元素数量。

如果您不想处理100种不同的元素,请考虑用户的感受!