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

Java WebDriver/PageObject/FindBy:如何使用动态值指定xpath?,java,selenium,xpath,selenium-webdriver,pageobjects,Java,Selenium,Xpath,Selenium Webdriver,Pageobjects,我试图在Java中使用页面对象模式,但在@FindBy/XPath方面遇到了一些问题 前面,我在Groovy中使用了以下构造: driver.findElement(By.xpath("//td[contains(text(),'$SystemName')]")).click() Here, SystemName is a parameter that can be different. 现在,我想做同样的事情,但要遵循Java中的页面对象范例: public class ManagedS

我试图在Java中使用页面对象模式,但在@FindBy/XPath方面遇到了一些问题

前面,我在Groovy中使用了以下构造:

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

Here, SystemName is a parameter that can be different. 
现在,我想做同样的事情,但要遵循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();

    }

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

SystemHomePage.deleteSystem("Firestone");
问题:如何通过PlantSystemName的符号和为deleteSystem指定的SystemName链接@FindBy

谢谢,
Racoon

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


请参见

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

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

看看这个


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

多亏了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();

}

为此,我使用了另一种解决方法,它允许我们使用动态xpath,甚至可以与页面工厂一起使用

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

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

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

你为什么不遵循java约定?java成员和方法应该是camelCased而不是PascalCased。谢谢,做了一些更改。这都是个人偏好,但根据java约定,我们使用camelCasing:)我对这两个都很满意。如果你对我的问题有任何线索,我将不胜感激:)Ardesco,谢谢!你指定的链接不包含任何变通方法。那么人们如何应对这一限制呢?这是因为没有一个限制,这是Java中注释的工作方式。人们通过不尝试做你想做的事情来应对这一限制。Ardesco,谢谢。所以我正确地理解有两种选择:1)只使用静态XPath。但这并不总是可能;2)不要使用PageFactory&annotation完全可以。我自己实现页面对象。在这种情况下,有什么最佳实践吗?您可以混合搭配,可以使用PageFactory和批注,还可以在页面对象中定义一些使用动态创建的XPath的By。Ardesco,谢谢!我根据您的建议发布了解决方案。它很有效。有没有关于如何做得更好的评论感谢。Robbie,首先,谢谢你的回答。说实话,我不太明白你的意思。你的意思是说,忘记Selenium WebDriver中内置的PageFactory/PageObject,只遵循模式本身,而不是它的内置实现是有意义的吗?即,用我自己的功能创建我自己的类?我不是我想说,你不必使用页面工厂来跟踪页面对象模式。我发现它对你发现的原因限制太多了。罗比,谢谢。好吧,让我们忘掉PageFactory。你如何用动态XPath实现WebLIST?entElement.findElement(By.xpath(String.format(“//tr/td[contains(text(),'%s')]”,SystemName))-稍微简单一点
waitForElement(parentElement)
getDynamicElement("System-A")