我正在测试一个仍在开发中的网站。
通常,元素的 id、类、文本或 DOM 中的位置会发生变化。然后我一直使用的定位器将不再能够找到该元素。
但是这些功能仍然可以正常运行。当没有实际回归时,我不希望几个测试失败。
因此,我没有为每个元素使用一个定位器,而是有一个定位器集合。
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 中更新它们,同时测试继续顺利运行。
以这种方式设置我的项目有什么优点或缺点?