在Selenium中每个元素使用多个定位器的优点/缺点?

时间:2013-06-06 18:43:44

标签: java testing selenium webdriver automated-tests

我正在测试一个仍在开发中的网站。

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中更新它们,同时测试继续顺利运行。

以这种方式设置项目有哪些优点或缺点?

1 个答案:

答案 0 :(得分:2)

这是一种有趣的方法,但我担心你可能会掩盖其他问题。我更愿意与开发人员更紧密地合作,以避免首先破坏UI问题。

是否动态生成更改ID?如果是这种情况,请查看您是否无法在ID上获得后缀,例如_loginlink。您可能还必须使用从附近的静态ID开始的XPath:“// div [@ id ='login_link_container'/ a”。 (从文档的根目录开始,就像你的示例节目一样痛苦!:))