如何使用ExtJS在页面上找到元素的唯一选择器以与Selenium一起使用?

时间:2013-08-02 17:45:58

标签: extjs xpath selenium webdriver selenium-webdriver

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

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

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

当我使用Firebug复制xPath时,我得到一个这样的值:

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

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

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

在该页面上,每个元素都具有此ID格式,因此CSS ID不能用于查找元素。

我希望得到xPath在DOM中的位置,但Firebug只会返回ID xPath,因为它对于该页面实例是唯一的。

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

如何让Firebug(或其他能以相似速度工作的工具)为我提供一个独特的选择器,即使在ext-gen ID发生变化后也可以用它来查找Selenium的元素?

3 个答案:

答案 0 :(得分:5)

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

提示1:不要使用像/div[4]/div[3]/div[4]/div/div/div/span[2]/span这样不可读的XPath。源代码的一个微小变化可能会导致DOM结构的变化。这将导致巨大的维护成本。

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

例如,this 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")获取。

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

答案 1 :(得分:1)

我建议您通过By.cssSelector("span[id^='ext-gen'])

在此实例中使用CSS

上述语句表示“选择id为以ext-gen开头的span元素”。 (如果它需要更具体,你可以回复,我会看看我是否可以帮助你。)

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

答案 2 :(得分: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/