4

我正在使用 Selenium 和 Firefox Webdriver 来处理页面上的元素,该页面具有唯一的 CSS ID(在每次页面加载时),但 ID 每次都会更改,因此我无法使用它们来定位元素。这是因为该页面是使用 ExtJS 构建的 Web 应用程序。

我正在尝试使用 Firebug 来获取元素信息。

我需要找到一个唯一的 xPath 或选择器,以便我可以使用 Selenium 单独选择每个元素。

当我使用 Firebug 复制 xPath 时,我得到如下值:

//*[@id="ext-gen1302"]

但是,下次加载页面时,它看起来像这样:

//*[@id="ext-gen1595"]

在该页面上,每个元素都有这种 ID 格式,因此无法使用 CSS ID 来查找元素。

我想获取根据其在 DOM 中的位置的 xPath,但 Firebug 只会返回 ID xPath,因为它对于该页面实例是唯一的。

/html/body/div[4]/div[3]/div[4]/div/div/div/span[2]/span

我怎样才能让 Firebug(或其他可以以类似速度工作的工具)为我提供一个独特的选择器,即使在 ext-gen ID 更改后,它也可以用于使用 Selenium 查找元素?

4

3 回答 3

5

ExtJS UI 自动化测试的另一个受害者,这里是我专门用于测试 ExtJS 的技巧。(但是,这不会回答您标题中描述的问题)

提示 1:永远不要使用不可读的 XPath,例如/div[4]/div[3]/div[4]/div/div/div/span[2]/span. 源代码的微小变化可能会导致 DOM 结构发生变化。这将导致巨大的维护成本。

提示 2:利用有意义的自动生成的部分 id 和类名。

例如,这个ExtJS 网格示例:By.cssSelector(".x-grid-view .x-grid-table")会很方便。如果有多个网格,请尝试索引它们或找到可识别的祖先,例如By.cssSelector("#something-meaningful .x-grid-view .x-grid-table").

提示 3:在源代码中创建有意义的类名。ExtJS 提供clstdCls用于自定义类名,因此您可以cls:'testing-btn-cancel'在源代码中添加,并通过By.cssSelector(".testing-btn-cancel").

Tip3是最好的也是最后一个。如果您无权访问源代码,请与您的经理交谈,Selenium UI 自动化确实应该是可以修改源代码的开发人员的工作,而不是像最终用户一样的测试人员。

于 2013-08-04T21:24:48.120 回答
1

我建议在这种情况下使用 CSSBy.cssSelector("span[id^='ext-gen'])

上述语句的意思是“选择一个 id 以 ext-gen 开头的 span 元素”。(如果需要更具体的可以回复,我看看能不能帮到你)。

或者,如果您想使用 XPath,请查看以下答案:Xpath for selection html id including random number

于 2013-08-02T17:50:05.003 回答
1

尽管如上所述在某些情况下不需要这样做,但您可以解析元素并生成 xpath id。

import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;

public class XPATHDriverWrapper {
Map xpathIDToWebElementMap = new LinkedHashMap();
Map webElementToXPATHIDMap = new LinkedHashMap();
public XPATHDriverWrapper(WebDriver driver){
    WebElement htmlElement = driver.findElement(By.xpath("/html"));
    iterateThroughChildren(htmlElement, "/html");
}

private void iterateThroughChildren(WebElement parentElement, String parentXPATH) {
    Map siblingCountMap = new LinkedHashMap();

    List childrenElements = parentElement.findElements(By.xpath(parentXPATH+"/*"));
    for(int i=0;i<childrenElements.size(); i++) {
        WebElement childElement = childrenElements.get(i);
        String childTag = childElement.getTagName();
        String childXPATH = constructXPATH(parentXPATH, siblingCountMap, childTag);
        xpathIDToWebElementMap.put(childXPATH, childElement);
        webElementToXPATHIDMap.put(childElement, childXPATH);
        iterateThroughChildren(childElement, childXPATH);
//          System.out.println("childXPATH:"+childXPATH);
    }
}

public WebElement findWebElementFromXPATHID(String xpathID) {
    return xpathIDToWebElementMap.get(xpathID);
}

public String findXPATHIDFromWebElement(WebElement webElement) {
    return webElementToXPATHIDMap.get(webElement);
}

private String constructXPATH(String parentXPATH,
        Map siblingCountMap, String childTag) {
    Integer count = siblingCountMap.get(childTag);
    if(count == null) {
        count = 1;
    } else {
        count = count + 1;
    }
    siblingCountMap.put(childTag, count);
    String childXPATH = parentXPATH + "/" + childTag + "[" + count + "]";
    return childXPATH;
}
}

另一个从 Document 生成 id 的包装器发布在:http ://scottizu.wordpress.com/2014/05/12/generating-unique-ids-for-webelements-via-xpath/

于 2014-05-12T23:18:33.873 回答