Java WebDriver/PageObject/FindBy:如何使用动态值指定 xpath?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21263367/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 07:45:51  来源:igfitidea点击:

WebDriver/PageObject/FindBy: how to specify xpath with dynamic value?

javaseleniumxpathselenium-webdriverpageobjects

提问by Racoon

I'm trying to use Page Objectpattern in Java and having some trouble with @FindBy/XPath.

我正在尝试在 Java 中使用页面对象模式,但在使用@FindBy/XPath 时遇到了一些麻烦。

Earlier, I used the following construction in Groovy:

早些时候,我在 Groovy 中使用了以下构造:

driver.findElement(By.xpath("//td[contains(text(),'$SystemName')]")).click()

Here, SystemName is a parameter that can be different. 

Now, I want to do the same thing but in accordance with Page Object paradigm in Java:

现在,我想做同样的事情,但要按照 Java 中的页面对象范式:

public class ManagedSystems {

    private WebDriver driver;

    @FindBy(id="menu_NewSystem")
    private WebElement menuNewSystem;

    @FindBy (xpath = "//td[contains(text(),'$SystemName')]")  // ??? How to use SystemName from deleteSystem method (below)?
    private WebElement plantSystemName;

    ....

    public SystemHomePage deleteSystem (String systemName) {

        plantSystemName.click();

    }

}

In my test, I call deleteSystem:

在我的测试中,我调用 deleteSystem:

SystemHomePage.deleteSystem("Firestone");

Question: How to link @FindBy notation for PlantSystemNameand SystemName specified for deleteSystem?

问题:如何链接@FindBy 符号的 PlantSystemName为 deleteSystem 指定的 SystemName

Thanks, Racoon

谢谢,浣熊

回答by Ardesco

You can't do that, Annotations are constant values stored in the class file. You can't compute them at runtime.

你不能这样做,注解是存储在类文件中的常量值。您无法在运行时计算它们。

See Can the annotation variables be determined at runtime?

请参阅可以在运行时确定注释变量吗?

回答by Robbie Wareham

You are using a page object factory rather than just following the page object pattern.

您正在使用页面对象工厂,而不仅仅是遵循页面对象模式。

You can create page objects as simple classes with identifiers stored as private variables, and methods exposing the elements using those variables, and you are still following the page object pattern.

您可以将页面对象创建为将标识符存储为私有变量的简单类,以及使用这些变量公开元素的方法,并且您仍然遵循页面对象模式。

check out this; http://relevantcodes.com/pageobjects-and-pagefactory-design-patterns-in-selenium/

看看这个;http://relevantcodes.com/pageobjects-and-pagefactory-design-patterns-in-selenium/

If your identifiers are just variables, then you can use any manipulation you want

如果您的标识符只是变量,那么您可以使用任何您想要的操作

回答by Racoon

Thanks to Ardesco and Robbie, I came up with the following solution:

感谢 Ardesco 和 Robbie,我想出了以下解决方案:

private String RequiredSystemNameXpath = "//td[contains(text(),'xxxxx')]";

private WebElement prepareWebElementWithDynamicXpath (String xpathValue, String substitutionValue ) {

        return driver.findElement(By.xpath(xpathValue.replace("xxxxx", substitutionValue)));
}

public void deleteSystem (String systemName) {


    WebElement RequiredSystemName = prepareWebElementWithDynamicXpath(RequiredSystemNameXpath, systemName);

    RequiredSystemName.click();

}

回答by Aftaab Siddiki

I used another workaround for this which will allow us to use dynamic xpath even with page factory.

我为此使用了另一种解决方法,即使使用页面工厂,它也允许我们使用动态 xpath。

Solution: Add the xpath of any parent element that is static and reference child element with dynamic path. In your case, //td[contains(text(),'$SystemName'), parent element of td might be 'tr' or 'table'. If table is static, use below code:

解决方案:添加任何静态父元素的 xpath,并使用动态路径引用子元素。在您的情况下,//td[contains(text(),'$SystemName'),td 的父元素可能是 'tr' 或 'table'。如果表是静态的,请使用以下代码:

@FindBy(xpath = "<..table xpath>")
public WebElement parentElement; 

public WebElement getDynamicEmement(String SystemName){
  parentElement.findElement(By.xpath("//tr/td[contains(text(),'"+SystemName+"')]"))
}

Now in your script, access table first(so that its reference is loaded in memory) and then call the getDynamicElement method.

现在在您的脚本中,首先访问表(以便将其引用加载到内存中),然后调用 getDynamicElement 方法。

waitForElement(parentElement)
getDynamicElement("System-A")