我正在测试一个仍在开发中的网站。
DOM中元素的id,类,文本或位置通常会发生变化。然后我一直在使用的定位器将无法再找到该元素。
但功能仍然正常运行。当没有实际的回归时,我不希望几个测试失败。
因此,我没有为每个元素设置一个定位器,而是有一组定位器。
public static final ArrayList<By> LOGIN_ANCHOR_LOCATORS = new ArrayList<By>();
static {
LOGIN_ANCHOR_LOCATORS.add(By.id("loginLink"));
LOGIN_ANCHOR_LOCATORS.add(By.linkText("Login"));
LOGIN_ANCHOR_LOCATORS.add(By.xpath("/html/body/div[5]/a"));
}
我找到元素的方法如下:
public WebElement locateElement(ArrayList<By> locators){
// create an element to return
WebElement element = null;
// until the desired element is found...
while (element == null){
// loop through the locators
for (By locator : locators){
// try to find by locator
element = customWait.until(ExpectedConditions.presenceOfElementLocated(locator));
// if not found...
if (element == null){
// log the failure
logFailingLocator(locator);
}
}
}
return element;
}
它尝试在集合中找到具有第一个定位符的元素,并且只有在它失败时,尝试下一个定位器。
集合是ArrayList
(订单由插入顺序定义),这意味着我的for loop
将按照添加到列表的顺序尝试每个定位器。
我通过按特定顺序添加定位器来初始化上面的列表。 Id是第一个,因为我认为元素在DOM中的位置是否会发生变化,但它会保留其id,那么这将是我最有可能找到正确元素的方式。 Xpath是最后一个因为即使id / class / text改变了,但是在该位置的DOM中仍然存在相同类型的元素,它可能是正确的元素,但可能不如其他定位器确定。
我正在使用流畅的等待忽略NoSuchElementException:
// Wait 5 seconds for an element to be present on the page, checking
// for its presence once every quarter of a second.
Wait<WebDriver> customWait = new FluentWait<WebDriver>(driver)
.withTimeout(5L, TimeUnit.SECONDS)
.pollingEvery(250L, TimeUnit.MILLISECONDS)
.ignoring(NoSuchElementException.class);
因此当一个定位器失败时,它不会破坏循环 - 它只记录失败,然后继续尝试下一个定位器。
如果所有定位器都失败,那么该元素将保持为空,测试将失败,并且更可能的原因是功能/功能的实际回归。
我会定期检查我的日志中是否有包含1个或2个失败定位器的元素,并在此期间在我的pageObject中更新它们,同时测试继续顺利运行。
以这种方式设置项目有哪些优点或缺点?
答案 0 :(得分:2)
这是一种有趣的方法,但我担心你可能会掩盖其他问题。我更愿意与开发人员更紧密地合作,以避免首先破坏UI问题。
是否动态生成更改ID?如果是这种情况,请查看您是否无法在ID上获得后缀,例如_loginlink。您可能还必须使用从附近的静态ID开始的XPath:“// div [@ id ='login_link_container'/ a”。 (从文档的根目录开始,就像你的示例节目一样痛苦!:))