我正在使用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的元素?
答案 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为自定义类名提供cls
和tdCls
,因此您可以在源代码中添加cls:'testing-btn-cancel'
,并通过By.cssSelector(".testing-btn-cancel")
获取。
提示3 是最好的,也是最后一个。如果您无法访问源代码,请与您的经理交谈,Selenium UI自动化应该是可以修改源代码的人的开发人员工作,而不是像最终用户那样的测试人员。
答案 1 :(得分:1)
我建议您通过By.cssSelector("span[id^='ext-gen'])
上述语句表示“选择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/