为什么在使用XPATHMapSelenium Web驱动程序的元素时会返回两个外观相同的元素

7ajki6be  于 2023-02-04  发布在  其他
关注(0)|答案(5)|浏览(177)

我有这个问题一段时间,但从来没有做过任何事情,当Map一些元素的UI测试,我有时会遇到元素返回2个相同的结果。
过去我们通过使用findelements然后使用索引[1]来解决这个问题
但是我仍然不明白为什么它返回2个元素,而我只能在应该定位的代码中看到1个。
下面是一个示例,您可以在下面看到此用户名字段框

如果我使用一些xpath

//input[@name='username']

我只希望得到1个元素作为返回,但是使用工具Chropath,我可以看到我得到2个元素作为返回

这些元素看起来完全相同,一个没有隐藏等。我一直不明白为什么会发生这种情况,因为如果我使用一个查找元素。我得到一个元素不可交互的错误,因为我猜驱动程序不能决定使用哪个?或者他们是在另一个的方式。
因此,我一直使用的变通方法是

return self.browser.find_elements(by=By.XPATH, value="//input[@name='username']")[1]

而我实际上应该能够使用

return self.browser.find_element(by=By.XPATH, value="//input[@name='username']")

任何有助于理解这一点的帮助都将不胜感激

    • 更新**

一些优秀的React,它让我明白了现在发生了什么,向前迈进,我将使用以下内容:

for e in self.browser.find_elements(by=By.XPATH, value="//input[@name='username']"):
            if e.is_displayed():
                return e

这似乎对我有用

p8ekf7hl

p8ekf7hl1#

当一个网站同时有桌面版和移动的版或小屏幕版时,我经常看到这种情况。在全屏(或接近全屏)时,桌面元素可见,而小屏幕元素隐藏。一旦你将浏览器调整到足够小,桌面元素隐藏,小屏幕元素可见。
你可以用一种通用的方法来解决这个问题,那就是根据可见性过滤返回的两个元素,例如:

return [e in self.browser.find_elements(by=By.XPATH, value="//input[@name='username']") if e.is_displayed()]

这应该总是返回两个元素中的可见元素。

hfsqlsce

hfsqlsce2#

答案就在快照中:

以下xpath

//input[@name='username']

标识HTML DOM中的2个不同元素。在两个匹配元素中,第一个匹配元素用于 * 移动的显示器 ,当您在 * 桌面模式 * 下访问DOM Tree时,该元素保持隐藏*。在给定的Chropath快照中,classname 作为 modal-content-mobile 是最佳提示。
溶液
在这些情况下,有不同的方法来识别所需的元素,虽然有些用户倾向于使用 index,有些用户倾向于探测 displayedness,但从个人Angular 来看,我发现向上遍历DOM以查找其祖先中属性值的差异,然后最终向下遍历直到所需的元素,这是相当容易和方便的。

a1o7rhls

a1o7rhls3#

页面上可能有多个具有相同名称属性的相同元素。必须隐藏其中一个元素。
如果你想访问第一个,使用下面的xpath。

return self.browser.find_element(by=By.XPATH, value="(//input[@name='username'])[1]")

如果要访问最后一个,请使用以下命令

return self.browser.find_element(by=By.XPATH, value="(//input[@name='username'])[last()]")
von4xj4u

von4xj4u4#

多个元素匹配同一个定位器的情况很常见。
例如,可以为登录实现几个代码块:一个用于计算机浏览器,另一个用于移动的浏览器等。适当的元素将根据您用来浏览该页面。
Selenium find_element总是返回与页面上传递的定位符匹配的first元素。
因此,在第一个匹配元素被隐藏的情况下,return self.browser.find_element(by=By.XPATH, value="//input[@name='username']")将总是返回该隐藏元素。
您需要使定位器更加精确以匹配所需的web元素。
"(//input[@name='username'])[2]"这样的定位器可能不错,但最好在这里使用unique parent元素,比如"//div[@class='pc_modal']//input[@name='username']",这样您的代码就像这样:

return self.browser.find_element(By.XPATH, "//div[@class='pc_modal']//input[@name='username']")
izj3ouym

izj3ouym5#

严格意义上来说,没有两个元素有相同的xpath。如果你看绝对路径,你会发现区别。关键是找到一个唯一的路径。在很多情况下,你会发现一个网页,你会发现许多文本框/标签/下拉列表有相同的id,但只是通过它们的绝对路径来区分。
大多数情况下,这取决于开发网页的框架和开发者的偏好。例如,使用React开发的应用程序将具有与使用Angular开发的应用程序不同的DOm结构。
是的,你是对的,在这种情况下很难找到感兴趣的元素。在这种情况下,不仅要依赖于特定的元素,还要添加一个父元素/wibling或祖先来访问该元素。虽然这可能需要一些时间,也可能很简单,但在大多数情况下,找到一个唯一的xpath是可能的。
有一些像Ranorex这样的测试自动化工具有一个对象浏览器(objext spy),可以用来固定任何web元素,并访问其属性,如隐藏/可见/启用等。

相关问题