Android 上多方式定位元素(python)

本文详细介绍了在Android UI自动化测试中通过classname、id、xpath等方法进行元素定位的操作,包括如何使用Python代码实现点击不同类型的元素(如tab框、ImageView、TextView)以完成点击tab操作。同时讨论了在定位过程中遇到的问题及解决方案。

在学习实际UI自动化测试的时候,首先就需要定位元素,然而定位元素也是最头疼的地方,因为元素各种控件名称的缺失会影响元素的准确定位。

下面针对Android上点击tab的操作来尝试一下多种方式的元素定位方法。

一个tab的组成可能是,一整个tab框,tab框中也可能包含ImageView或TextView,那么其实只要实现点击其中一种都可完成点击tab的操作了。

例子项目中,tab可拆分成元素1(一整个tab框)、元素2(ImageView)和元素3(TextView)。 
(一)元素1,如下图: 
元素1 
红框标注的就是那个tab框

在图片左侧是元素1对应的所有属性,这里对定位元素有帮助的主要有type(对应classname)、resource-id(对应id)和xpath(对应xpath)。

由于元素1缺失resource-id,要实现点击这个tab框,这里我们只能通过classname和xpath去定位了。 
classname方法:

<code class="language-python hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">self.driver.find_elements_by_class_name(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"android.support.v7.app.ActionBar.e"</span>).__getitem__(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>).click()</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

因为classname在该界面不唯一,所以加了getitem来区分第几个。

xpath方法:

<code class="language-python hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">self.driver.find_element_by_xpath(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"//android.widget.LinearLayout[1]/android.support.v7.app.ActionBar.e[2]"</span>).click()</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

用xpath来定位基本不知道是干啥的,一般都得加备注,不然维护起来很麻烦。

(二)元素2,如下图: 
元素2 
这里红框标注的是tab框中的ImageView,通过点击该元素也可以实现点击tab的操作。 
classname方法:

<code class="language-python hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">self.driver.find_elements_by_class_name(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"android.widget.ImageView"</span>).__getitem__(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>).click()</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

id方法:

<code class="language-python hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">self.driver.find_elements_by_id(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"com.boohee.secret:id/iv_icon"</span>).__getitem__(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>).click()</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

xpath方法:

<code class="language-python hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">self.driver.find_element_by_xpath(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"//android.widget.LinearLayout[1]/android.support.v7.app.ActionBar.e[2]/android.widget.RelativeLayout[1]/android.widget.ImageView[1]"</span>).click()</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

(三)元素3,如下图: 
元素3 
这里红框标注的是tab框中的TextView,通过点击该元素也可以实现点击tab的操作。 
classname方法:

<code class="language-python hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">self.driver.find_elements_by_class_name(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"android.widget.TextView"</span>).__getitem__(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>).click()</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

id方法:

<code class="language-python hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">self.driver.find_elements_by_id(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"com.boohee.secret:id/tv_tab"</span>).__getitem__(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>).click()</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

xpath方法:

<code class="language-python hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">self.driver.find_element_by_xpath(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"//android.widget.LinearLayout[1]/android.support.v7.app.ActionBar.e[2]/android.widget.RelativeLayout[1]/android.widget.TextView[1]"</span>).click()</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

上面用的是绝对路径,由于元素3的text有值,这边也可以用相对路径来实现:

<code class="language-python hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">self.driver.find_element_by_xpath(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"//*[@text='超模25']"</span>).click()</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

那么看到这里,会发现在Android上classname和id定位时都用到了getitem来区分第几个,而xpath又特别不易理解,维护起来都不太方便。 
如果程序中同一个界面上,元素的classname或id是唯一的话,定位元素将会方便很多。

在使用 Appium 进行 Android 应用的 UI 自动化测试时,通过父元素 `android.widget.LinearLayout` 查找其子元素是一种常见的需求。可以通过多种方式实现这一目标,包括使用 **XPath**、**Android UIAutomator** 以及 **层级查找方法**。以下是几种常用的方法: ### 使用 XPath 定位元素 XPath 是一种灵活且强大的定位方式,可以基于父元素的属性来定位元素。例如,如果要定位 `LinearLayout` 下的某个子元素,可以使用如下 XPath 表达式: ```python # 定位 LinearLayout 父元素下的所有子元素 elements = driver.find_elements_by_xpath("//android.widget.LinearLayout/*") # 定位特定类型的子元素,例如 ImageView element = driver.find_element_by_xpath("//android.widget.LinearLayout/android.widget.ImageView") ``` 如果父元素具有特定的属性(如 `resource-id` 或 `text`),可以进一步细化 XPath 表达式: ```python # 根据父元素的 resource-id 定位元素 element = driver.find_element_by_xpath("//android.widget.LinearLayout[@resource-id='your.resource.id']/android.widget.Button") ``` ### 使用 Android UIAutomator 定位 Android UIAutomator 是 Appium 提供的一种原生定位方式,适用于复杂的 UI 结构。可以通过 `find_element_by_android_uiautomator` 方法实现定位: ```python # 定位 LinearLayout 父元素 parent_element = driver.find_element_by_android_uiautomator('new UiSelector().className("android.widget.LinearLayout")') # 从父元素中查找子元素 child_element = parent_element.find_element_by_android_uiautomator('new UiSelector().className("android.widget.Button")') ``` ### 使用层级查找方法 Appium 提供了基于层级结构的查找方法,可以通过父元素查找子元素: ```python # 定位 LinearLayout 父元素 parent_element = driver.find_element_by_class_name("android.widget.LinearLayout") # 从父元素中查找所有子元素 child_elements = parent_element.find_elements_by_class_name("android.widget.Button") ``` ### 处理多个子元素的情况 如果 `LinearLayout` 包含多个相同类型的子元素(如多个 `Button`),可以通过索引访问特定的子元素: ```python # 定位所有 Button 子元素 buttons = parent_element.find_elements_by_class_name("android.widget.Button") # 点击第一个 Button buttons[0].click() ``` ### 相关问题 在实际应用中,可能会遇到多个层级嵌套的情况,例如父元素的父元素也需要参与定位。此时可以结合多级 XPath 表达式进行定位: ```python # 定位祖父元素下的 LinearLayout 父元素,再查找其子元素 element = driver.find_element_by_xpath("//android.widget.FrameLayout/android.widget.LinearLayout[@index='0']/android.widget.Button") ``` ### 总结 通过上述方法,可以在 Android 应用中使用 Python 和 Appium 定位 `android.widget.LinearLayout` 父元素下的子元素。选择合适的方法取决于具体的 UI 结构和测试需求。对于复杂的 UI 层级,XPath 提供了更灵活的定位能力,而 Android UIAutomator 则适用于需要与原生控件交互的场景 [^1]。 ```python # 示例:点击 LinearLayout 下的第一个 Button parent_element = driver.find_element_by_class_name("android.widget.LinearLayout") buttons = parent_element.find_elements_by_class_name("android.widget.Button") if buttons: buttons[0].click() ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值