Java Selenium WebElement.findElements未按预期工作

Java Selenium WebElement.findElements未按预期工作,java,selenium,Java,Selenium,我正在使用Java和Selenium测试一个web应用程序。我试图单击页面上的一个按钮,其中存在两个具有相同类名和文本的按钮。因此,我首先找到父元素,然后在其子元素中查找我的按钮。我正在执行以下操作并获得意外结果 public static List<WebElement> findSubElementsUsingHtmlXpathClass(String htmlElement, String className, WebElement parent) {

我正在使用Java和Selenium测试一个web应用程序。我试图单击页面上的一个按钮,其中存在两个具有相同类名和文本的按钮。因此,我首先找到父元素,然后在其子元素中查找我的按钮。我正在执行以下操作并获得意外结果

public static List<WebElement> findSubElementsUsingHtmlXpathClass(String htmlElement,
        String className, WebElement parent) {
    String xPathString="//" + htmlElement + "[contains(@class, '" + className + "')]";

    List<WebElement> elements = parent.findElements(By.xpath(xPathString));
    return elements;
}
公共静态列表使用inghtmlxpath类(字符串htmlElement,
字符串类名称,WebElement父级){
字符串xPathString=“/”+htmlElement+”[包含(@class,“+className+”)];
List elements=parent.findElements(By.xpath(xPathString));
返回元素;
}
这将返回不属于父元素的元素

这就是我所说的:

String htmlElement = "div";
    String className = "tabs-container";
    List<WebElement> elements = Common.findElementsUsingHtmlXpathClass(driver, htmlElement, className);
    Common.myPrint(thisClass + " no of elements found: " + elements.size());
    for (WebElement element : elements) {
        // outerHTML: <input class="form-control btn btn-info" value="Create item"
        // type="button">
        // inner:
        String htmlElement2 = "input";
        String className2 = "form-control btn btn-info";
        String textToFind = "Create item";
        List<WebElement> subElements = Common.findSubElementsUsingHtmlXpathClass(htmlElement2, className2,
                element);HTML
String htmlElement=“div”;
String className=“制表符容器”;
列表元素=Common.findElementsUsingHtmlXpathClass(驱动程序、htmlElement、类名);
Common.myPrint(thisClass+“未找到元素:”+elements.size());
for(WebElement:elements){
//外层TML:
//内部:
字符串htmlElement2=“输入”;
String className2=“表单控制btn btn信息”;
String textToFind=“创建项”;
List subElements=Common.findsubelementsusingtmlxpathclass(htmlElement2,className2,
元素);HTML
我错过什么了吗


我已经能够解决这个问题,只需忽略它返回的第一个元素,但这只能在这种特定情况下得到保证。

尝试使用CSS选择器而不是XPath:

public static List<WebElement> findSubElementsUsingCSS(String className, WebElement parent) {
        String cssString="." + className;

        List<WebElement> elements = parent.findElements(By.cssSelector(cssString));
        return elements;
    }
公共静态列表使用CSS(字符串类名称,WebElement父元素)查找子元素{
字符串cssString=“.”+类名;
List elements=parent.findElements(By.cssSelector(cssString));
返回元素;
}

尝试使用CSS选择器而不是XPath:

public static List<WebElement> findSubElementsUsingCSS(String className, WebElement parent) {
        String cssString="." + className;

        List<WebElement> elements = parent.findElements(By.cssSelector(cssString));
        return elements;
    }
公共静态列表使用CSS(字符串类名称,WebElement父元素)查找子元素{
字符串cssString=“.”+类名;
List elements=parent.findElements(By.cssSelector(cssString));
返回元素;
}

您的XPath需要按如下所示进行更改:。需要在双斜杠之前添加。您需要从当前父元素中选择子元素。因此,在XPath中,需要指定,。以将其指示为当前节点

public static List<WebElement> findSubElementsUsingHtmlXpathClass(String htmlElement,
        String className, WebElement parent) {
    String xPathString=".//" + htmlElement + "[contains(@class, '" + className + "')]";

    List<WebElement> elements = parent.findElements(By.xpath(xPathString));
    return elements;
}
公共静态列表使用inghtmlxpath类(字符串htmlElement,
字符串类名称,WebElement父级){
字符串xPathString=“../”+htmlElement+”[包含(@class,“+className+”)];
List elements=parent.findElements(By.xpath(xPathString));
返回元素;
}

您的XPath需要按如下所示进行更改:。需要在双斜杠之前添加。您需要从当前父元素中选择子元素。因此,在XPath中,需要指定,。以将其指示为当前节点

public static List<WebElement> findSubElementsUsingHtmlXpathClass(String htmlElement,
        String className, WebElement parent) {
    String xPathString=".//" + htmlElement + "[contains(@class, '" + className + "')]";

    List<WebElement> elements = parent.findElements(By.xpath(xPathString));
    return elements;
}
公共静态列表使用inghtmlxpath类(字符串htmlElement,
字符串类名称,WebElement父级){
字符串xPathString=“../”+htmlElement+”[包含(@class,“+className+”)];
List elements=parent.findElements(By.xpath(xPathString));
返回元素;
}

我不能100%确定我是否理解该用例,但这看起来是一种非常迂回的方法。为什么不使用CSS选择器,只选择一个您想要的按钮?它可能看起来像这样:#parentId.class of-button@MetarevenCSS选择器在我正在测试的系统中几乎没有用处,因为有e没有永久性的结构。该网站使用Google Web Toolkit,因此所有ID和CSS地址都是可变的。引用一个模因:“耶稣基督,多么可怕”。无论如何,这不可能完全正确,否则你的示例将永远失败,因为你依赖于示例中具有固定类名的元素(选项卡容器、表单控件、btn、btn信息)。在您的示例中,我看不到任何css选择器无法完成的操作。我不能100%确定我是否理解该用例,但这看起来是一种非常迂回的操作方式。为什么不使用仅选择所需一个按钮的css选择器呢?它可以是这样的:#parentId.class of-button@MetarevenCSS-s事实证明,选民在我正在测试的系统中没有什么用处,因为没有永久性的结构。该网站使用谷歌网络工具包,因此所有ID和CSS地址都是可变的。引用一个模因:“耶稣基督,多么可怕啊”。无论如何,这不可能完全正确,否则您的示例将始终失败,因为您依赖于示例中具有固定类名的元素(制表符容器、表单控件、btn、btn信息)。在您的示例中,我看不到任何无法使用css选择器完成的操作。这不起作用。此项目的css选择器(来自Firefox)是.margin-top-10>div:nth-child(1)>div:nth-child(1)>div:nth-child(1)>input:nth-child(1),但在不同的运行中可能会有所变化。但是,您只能使用css选择器获取带有类的元素[@Stevestape认为CSS选择器非常糟糕,您基本上不应该使用从浏览器中自动生成的选择器。我强烈建议您阅读CSS选择器及其工作原理,因为这通常是选择元素的最简单方法,而且与xpath选择器相比,xpath选择器更易于维护和阅读,尽管xpath selectors可以更表达感谢@Metareven,我已经有了这个问题的答案。这不起作用。这个项目的CSS选择器(来自Firefox)是。margin-top-10>div:nth child(1)>div:nth child(1)>div:nth child(1)>input:nth child(1),但在运行时可能会发生变化。但您只能使用css选择器[@Stevestape]获取类元素,css选择器非常糟糕,您基本上不应该使用从浏览器中获取的自动生成选择器。我强烈建议您阅读css选择器