当容器的位置每次都可以改变时,有没有更好的方法从下拉列表中选择一个项目

Posted

技术标签:

【中文标题】当容器的位置每次都可以改变时,有没有更好的方法从下拉列表中选择一个项目【英文标题】:Is there a better way to select an item from a dropdown list when the location of the containers can change each time 【发布时间】:2021-12-14 08:51:10 【问题描述】:

我正在尝试从下拉列表中选择特定项目,但是页面上列表的位置可能会随着每次运行而改变。

目前我的代码试图找到下拉列表,单击它,然后根据页面中下拉列表的位置选择特定元素 - 不幸的是,body 中包含的 div 的位置可以是每次负载都不同,因此对数组计数器进行硬编码在后续运行中不起作用 - 即,在 /html/body/div[16] 中,16 可以更改:

IWebElement questType = _driver.FindElement(By.XPath("/html/body/div[4]/div/div/div/div[4]/table/tbody/tr[2]/td[2]/div/div[4]/table/tbody/tr[2]/td[2]/div/div/div[2]/div/div[4]/table/tbody/tr/td[5]/span[1]/span"));

questType.Click();
IWebElement slctquestType = _driver.FindElement(By.XPath("/html/body/div[16]/div/div[3]/ul/li[1][contains(text(),'" + Questn_Type + "')]"));
slctquestType.Click();

选择元素如下所示:

<ul unselectable="on" class="k-list k-reset" tabindex="-1" aria-hidden="true" id="TypeId_listbox" aria-live="off" data-role="staticlist" role="listbox">
  <li tabindex="-1" role="option" unselectable="on" class="k-item" aria-selected="false" data-offset-index="0">Data</li>
  <li tabindex="-1" role="option" unselectable="on" class="k-item" aria-selected="false" data-offset-index="1">Other</li>
  ...
</ul>

【问题讨论】:

&lt;ul unselectable="on" class="k-list k-reset" tabindex="-1" aria-hidden="true" id="TypeId_listbox" aria-live="off" data-role="staticlist" role="listbox"&gt;&lt;li tabindex="-1" role="option" unselectable="on" class="k-item" aria-selected="false" data-offset-index="0"&gt;Data&lt;/li&gt;&lt;li tabindex="-1" role="option" 你可以编辑你的问题 【参考方案1】:

XPath 非常强大。使用这种直接路径是最简单的方法。您还可以执行其他类似的操作来找到您想要的元素:

在节点内搜索一些文本:

By.XPath("//*[contains(text(), 'message part')]")

查找具有特定标题的按钮:

By.XPath("//button[@title = 'Continue']")

使用特定的类名查找 div 元素,该类名有一个子 div 元素,其标题中有一些文本:

By.XPath("//div[@class='className']//div[contains(@title, 'Title')]")

如您所见,您可以使用大量信息来查找特定元素。什么最符合您的具体情况取决于您,您可能应该查看有关 XPath syntax 的更多文档以深入了解。

【讨论】:

【参考方案2】:

这里有一些隐藏的复杂性,因为这不是传统的&lt;select&gt; 元素。据推测,javascript 正在打开和关闭下拉菜单。切换下拉菜单时,这些元素可能会淡入或淡出(或向上或向下滑动)。当这些元素处于淡出或向上或向下滑动的过程中时,Selenium 将无法点击它们。这不仅仅是定位器问题,也是时间问题。

您可能需要点击下拉菜单,然后等待。单击该选项,然后再次等待。由于逻辑不平凡,请考虑使用Page Object Model Design Pattern 来封装此行为。

要更直接地处理您的代码,请首先通过 HTML 标记 ID 找到下拉列表。 HTML 标记 ID 在网页上是唯一的。如果它们不是唯一的,则应该解决此问题,因为 HTML 规范声明 HTML 标记 Id 值在网页上应该是唯一的。

var wait = new WebDriverWait(_driver, TimeSpan.FromSeconds(30));
var questType = _driver.FindElement(By.Id("TypeId_listbox"));

questType.Click();

var optionLocator = By.XPath("//ul[@role = 'listbox']/li[contains(text(),'" + Questn_Type + "')]");
var slctquestType = wait.Until(ExpectedConditions.ElementIsClickable(optionLocator);

slctquestType.Click();
wait.Until(ExpectedConditions.InvisibilityOfElementLocated(optionLocator);

要记住的重要一点是 XPath 选择器不需要精确。两个连续的正斜杠字符// 返回文档树中任意深度的元素。这允许您跳过几个级别,并仅定位您感兴趣的元素。例如,查找列表框选项可以简化为:

"//ul[@role = 'listbox']/li[contains(text(),'" + Questn_Type + "')]"

最初的// 字符将在任何级别的文档树中搜索&lt;ul&gt; 标记。这使得 xpath 表达式对 HTML 结构的变化更具弹性,这将导致更稳定的测试。

【讨论】:

以上是关于当容器的位置每次都可以改变时,有没有更好的方法从下拉列表中选择一个项目的主要内容,如果未能解决你的问题,请参考以下文章

当 SuperViews 约束改变时更新 SubView 约束

当vector使用erase 数组长度是不是改变

方向改变后播放位置重置为零

有没有比我的实现更好的方法来检查更新的文件?

在 Windows phone 8.1 中实时跟踪位置

当用户改变当前位置时,核心位置框架的哪个函数被调用?