当前位置: 首页 > 知识库问答 >
问题:

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

乜清野
2023-03-14

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

元素的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中的该位置仍然存在相同类型的元素,它可能是正确的元素,但可能比其他定位器更不确定。

我使用的是忽略NoTouchElementException的流畅等待:

// 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);

所以当一个定位器失败时,它不会中断循环——它只是记录失败,然后仍然继续尝试下一个定位器。

如果所有定位器都失败了,那么元素将保持null,测试将失败,更可能的原因是特性/功能的实际回归。

我定期检查我的日志中有1或2个失败定位器的任何元素,并在此期间在我的pageObject中更新它们,同时测试继续顺利运行。

以这种方式设置项目的利弊是什么?

共有1个答案

仲孙凡
2023-03-14

这是一个有趣的方法,但我担心你可能掩盖了其他问题。我更愿意与开发人员更紧密地合作,以避免首先出现用户界面问题。

更改的ID是动态生成的吗?如果是这样的话,看看你是否不能在身份证上找到后缀,比如_loginlink。您可能还必须使用从附近的静态ID开始的XPath:"//div[@id='login_link_container'/a"。(从文档的根开始,就像你的例子显示的那样,这是一个痛苦的处方!:))

 类似资料:
  • 我正在使用selenium创建kahoot机器人泛滥器。(kahoot.it)我正在尝试使用selenium来定位输入框以及确认按钮。每当我尝试将它们定义为变量时,我都会得到这个。"命令引发了一个异常:TimeoutException: Message:",我认为这意味着我设置的5秒已过期,这意味着该元素从未被定位。 我试图定位一个“Iframe ”,但并不成功(可能做错了),但我已经搜索了几个小

  • 本文向大家介绍使用CSS为其父元素的第一个子元素的每个 元素设置样式,包括了使用CSS为其父元素的第一个子元素的每个 元素设置样式的使用技巧和注意事项,需要的朋友参考一下 要设置作为其父级第一个子级的每个<p>元素的样式,请使用CSS:first-child选择器。 示例 您可以尝试运行以下代码来实现:first-child选择器-

  • 问题内容: 在我的一项测试中,我正在使用定位元素: 匹配查询的元素不止一个,但是由于我只需要第一个元素,选择器就可以了。 问题是,抛出警告: 警告-为定位器By.cssSelector(“ ul.nav button”)找到了多个元素-将使用第一个结果 是否可以取消警告?换句话说,如何让我知道自己已意识到问题并且不希望再显示警告? 使用开发版本(直接从master分支安装)。 问题答案: 尝试以下

  • 我正在尝试为以下内容定位元素: 我尝试了XPath和CssSelector,但它无法定位元素。有人能帮我找到元素TIA吗

  • 我正在尝试点击图中所示的下拉菜单 这就是我尝试过的 但它给了我这个错误 NoSuchElementException: Message:找不到element://div[@ class = ' choosed-container choosed-container-single ']//a[@ class = ' choosed-single choosed-single-with-deselec

  • 在这种情况下使用any()的正确方式是什么?或者更好的是,需要做什么才能使这种方法发挥作用? 假设Selenium.get('url')在调用此方法之前已经执行。