写点什么

软件测试 | 高级定位技巧

  • 2023-02-17
    北京
  • 本文字数:4885 字

    阅读完需:约 16 分钟

通常使用定位工具定位 App 页面上的元素会发生定位不到元素或者定位元素失败的情况。发生这种情况可能是 App 的页面不唯一,也可能是 App 的页面发生了变化。下面介绍定位元素的高级用法,使用层级关系定位或者多重属性定位的方式来确定了 App 页面元素的唯一性,从而更精准、更稳定地定位到我们想要 App 页面元素。

1.XPath 高级定位技巧

(1)XPath 简介

XPath 的英文全称为 XML Path Language,意为对 XML 中的元素进行路径定位的一种语言,它使用与 XML 标记语言、HTML 标记语言,App Dom 结构。XPath 是我们做自动化测试中进行元素定位时用的比较多的工具,它可使用与 Seleniu、Appium 和 Appcrawler。前面章节已经对 XPath 进行了一些说明,下面只对 XPath 做举例说明。


(2)XPath 基本语法

表 5-4 是 XPath 的常用方法。


(3)XPath 模糊定位技巧


XPath 中的 contains()是模糊匹配的定位方法,若在定位元素时,一个元素的属性不固定,这时就可以用模糊匹配来定位元素。使用格式为//[contains(@content-desc,'帮助')],示例代码如下(Python 版和 Java 版)。

Python 版

driver.find_element(By.XPATH,'//*[contains(@text,"测试")]')
driver.find_element(By.XPATH,'//*[contains(@content-desc,"搜索")]')
driver.find_element(By.XPATH,'//*[contains(@resource-id,"login_phone")]')
复制代码


Java 版本

driver.findElement (By.xpath(       "//*[contains(@text,\"测试")]"));      driver.findElement(By.xpath(        "//*[contains(@content-desc,\"搜索"\)]"));        driver.findElement(By.xpath(         "//*[contains(@resource-id,\"login_phone\")]"));
复制代码


(4)XPath 组合定位技巧

用 XPath 可以同时匹配两个甚至多个属性来完成元素定位。这里常用的属性有 text、resource-id、class、index、content-desc 等,任意组合这些属性完成定位,示例代码如下(Python 版和 Java 版)。


Python 版本

driver.find_element(    By.XPATH,'//*[@text="我的" and @resource-id="tab_name"]'    ).click()    driver.find_element(    By.XPATH,'//*[@text="注册/登录" and @index="1"]    ').click()
复制代码


Java 版本

driver.findElemnt(By.xpath(     "//*[@text=\"我的\ and @resource-id=\"tab_name\"]")).click();     driver.findElement(By.xpath(      "//*[@text=\"注册/登录\" and @index=\"1"]")).click();
复制代码


(5)XPath 层级定位

我们定位元素的时候可能会设计通过子元素去定位父元素,或者用父元素定位子元素,或者定位兄弟元素,XPath 支持父子关系、兄弟关系元素的查找与定位。示例代码如下(python 版和 Java 版)。


Python 版本

# 通过子元素定位父元素# 方法一: ..driver.find_element_by_xpath(   '//*[@text="手机号"]//..').tag.name   # 方法二:parent::*driver.find_element_by_xpath(    '[@text="手机号"]/parent::*').tag.name    #通过某元素定位其兄弟元素driver.find_element_by_xpath(    '//*[text="手机号"]/../li'    ).tag_name
复制代码


Java 版本

//通过子元素定位父元素//方法一:..driver.findElement(By.xpath(  "//*[@text=\"手机号\"]/..")).getTagName();  //方法二 parent::*driver.findElement(By.xpath(   "[@text=\"手机号\"]/parent::*")).getTagName();   //通过某元素定位其兄弟元素driver.find_Element(By.xpath(    "//*[@text=\"手机号\"]/../li"    )).getTagName();
复制代码

2.实例案例

(1)场景一

App 应用:雪球 apk。


我们首先使用 UI Automator Viewer 工具对该 App 进行 DOM 分析,然后使用 XPath 对分析到的元素进行定位,如图 5-14 所示的搜索框,我们可以使用元素的多种元素对搜索框进行定位,常用的属性有 text、resource-id、class 和 content-desc 等。


这里推荐使用 resource-id 进行定位,通常情况下,它是 App 页面元素的卫衣属性,用 XPath 编程实现定位的代码如下(Python 版和 Java 版)。


Python 演示代码

driver.find_element(    By.XPATH,'//*[contains(@resource-id,"tv_search")]') # 或者也可以写成下面这样 driver.find_element(By.ID,'tv_search')
复制代码


Java 演示代码

driver.findElement(By.xpath("//*[contains(@resource-id,        \"tv_search\")]"));//或者也可以写成下面这样driver.findElement(By.id("tv_search"));
复制代码


(2)场景二

如图 5-15 所示,获取 “ BABA”所对应的股票价格 “187.11”,可以使用 XPath 父关系来进行元素定位。


定位实现的代码如下(Python 版和 Java 版)


Python 演示代码

curr_price = self.driver.find_element(   MobileBy.XPath,"//*[@text='BABA']/../../..\   //*[@resource-id='com.xueqiu.android:id/current_price']")
复制代码


Java 演示代码

MobileElement curr_price = driver.findElement(      By.xpath("//*[@text=\"BABA\"]/../../..//\      *[@redource-id='com.xueqiu.android:id/current_price']"));
复制代码

3.UIAutomator 定位技巧

UiAutomator 是 Android SDK 自带的一个测试框架,这个测试框架提供了一些列的 API,用这些 API 可以与用 Android 开发的 APP 进行交互,例如,打开菜单、点击、滑动等。当 Appium 的 Caps 参数 uiautomatorName 设置为 UiAutomator2 时,就能够实现计算机端与手机端的 UiAutomator 通信,并且我们可以使用 UiAutomator 执行测试代码。UiAutomator1 是比较旧的版本,如果想测试较旧版本的基于 Android 系统开发的 App(低于 Android 4.4 版本),需要设置 Appium 的 Caps 参数:uiautomationName="UiAutomator1"。


由于 UiAutomator 是 Android SDK 自带的 “工作引擎”,使用这个测试框架进行元素定位,执行速度要比用 XPath 定位元素快很多。但由于 UiAutomator 的用法比较特殊,调试起来相对麻烦,如果测试脚本中的定位语句编写不当,脚本编辑器也不会给出任何错误提示信息,只能在运行的时候检验测试脚本的对错。


下面就单独介绍一下基于 UiAutomator 定位元素的方法,基本语法如下(Python 版和 Java 版)。


Python 版本

driver.find_elemnet_by_android_uiautomator()
复制代码


Java 版本

driver.findElement(MobileBy.AndroidUIAutmator());
复制代码


常用的 UiAutomator 方法如下:

UiSelenium()   #实现元素定位UiScrollable() #实现滚动查找元素
复制代码


(1)通过 text 定位

UiSelector()的用法与 XPath 类似,可以通过元素的 text 属性来定位元素。Uiselector 的语法格式如下:

new UiSelector().text("text文本")
复制代码


UiSelector 也适用模糊查询的方式来定位元素。

UiSelector 的演示代码如下(Python 版和 Java 版)。

Python 版本

driver.find_element_by_android_uiautomator(    'new UiSelector().textContains("手机")').click()
复制代码


Java 版本

driver.findElementByAndroidUIAutomator(\    "new UiSelector().textContains(\"手机\")").click();
复制代码


(2)通过 resourceId 定位

UiAutomator 同样也能用 ID 定位元素,格式为 new UiSelector().resourceId("resource-id 属性"),示例代码如下(Python 版和 Java 版本)。


Python 版本

driver.find_element_by_android_uiautomator(    'new UiSelector().resourceId("rl_login_phone")').click()
复制代码


Java 版本

driver.findElementByAndroidUIAutomator("new UiSelector().\resourceId(\"rl_login_phone\")").click();
复制代码


(3)通过 className 定位

App 页面上元素的 class 属性一般不唯一,此时可以根据下标对元素定位,格式 new UiSelector().className("className"),一般使用 find_elements 完成元素定位,示例代码如下(Python 版和 Java 版)。


Python 版本

driver.find_elements_by_android_uiautomator(  'new UiSelector().\  className("android.widget.TestView"))'[5].click()
复制代码


Java 版本

driver.findElementsByAndroidUIAtor("new UiSelector().\className(\"android.widget.TestView\")")[5].click();
复制代码


(4)通过 description 定位

description 也支持 content-desc 定位方式,格式为 new UiSelector().description("content-des"属性),示例代码如下(Python 版和 Java 版)。


Python 版本

driver.find_element_by_android_uiautomator(  'new UiSelector().description("搜索")').click()
复制代码


Java 版本

driver.findElementByAndroidUIAutomator("new \UiSelector().description(\"搜索\")").click();
复制代码


(5)组合定位方式

UiAutomator 也支持属性组合定位元素,示例代码如下(Python 版和 Java 版)。

Python 版本

driver.find_element_by_android_uiautomator( 'new UiSelector().resourceId(\ "com.xueqiu.android:id/tv_login_phone").text("手机号")').click();
复制代码


Java 版本

driver.findElementByAndroidUIAutomator("new UiSelector().resourceId(\\"com.xueqiu.android:id/tv_login_phone\").text(\"手机号\")").click();
复制代码


(6)滚动查找元素

UiAutomator 使用 UiScrollable()方法可以滚动查找指定的某个元素,示例代码如下(Python 版和 Java 版)。

driver.find_element_by_android_uiautomator(  'new UiScrollable(new UiSelector().scrollable(true\  .instance(0)).scrollIntoView(new UiSelector()\  .text("我的").instance(0);').)click()
复制代码


Java 版本

driver.findElementByAndroidUIAutomator(\  "new UIScrollable(new UiSelector().scrollable(ture)\  .instance(0)).scrllIntoView(new UiSelector().\  text(\"我的\").instance(0));").click();
复制代码


上面的测试代码作用是,在当前的页面滚动查找 text 属性值是 “我的” 这个元素,找到之后执行点击操作。

4.css selector 元素定位

Appium Server 从 1.19.0 版本开始,增加了用 css selector 方式进行元素定位的支持,即 appiumuiautomator2-driver 会将 css selector 定位方式转化成 UiAutomator 定位方式。


注意:Appium Inspector 中暂时没有添加这种定位当时。


由于 UiSelector()的表达式用的是 Java 格式的语法,因此编写定位元素的表达式很复杂,且在用工具编写代码时(如 Pycharm、VSCode、IntelliJ IDEA 等工具),若代码编写错误也不会有任何提示信息。只能是代码运行时才能发现其中表达式的错误。css selector 的语法会自动转成 UiAutomator 的语法结构,这种官方提供的原生的定位元素的方式,定位速度更快一些。


(1)ID 定位


css selector 可以用 ID 进行元素定位。飞马如下(Python 版和 Java 版)(#igk 表示 css selector 定位符)。


Python 版本

driver.find_element_by_css_selector('#igt')driver.find_element_by_id_('android:id/igk')
复制代码


Java 版本

driver.findElementByCssSelector("#igk").click();driver.findElementById("android:id/igk").click();
复制代码


(2)class name 定位

css selector 使用 class name 进行元素定位的代码如下(Python 版和 Java 版)(css selector 的定位符为.android.widget.ImageView)。


Python 版本

driver.find_element_by_css_selector('.android.widget.ImageView')driver.find_element_by_class_name("android.widget.ImageView")
复制代码


Java 版本

driver.findElementByCssSelector(".android.widget.ImageView");driver.findElementByClassName("android.widget.ImageView");
复制代码


(3)text 定位


css selector 使用 text 进行元素定位的代码如下(Python 版和 Java 版)(css selector 的定位符为“*[text=‘工作台’]”)。


Python 版本

driver.find_element_by_css_selector("*[text='工作台']")
复制代码


注:对应 XPath 定位器的代码时 driver.find_element_by_xpath("//*[@text='工作台']")。


Java 版本

driver.findElementByCssSelector("*[text=\"工作台\"]");
复制代码


注:对应 XPath 定位器的代码是 driver.findElementByXPath("//*[@text= \ "工作台"]").


(4)description 定位


css selector 使用 description 进行元素定位的代码如下(Python 版和 Java 版)(css selector 的定位符为*[description="ContentDescription"])。

Python 版本

driver.find_element_by_scc_selector('*[description="ContentDescription"]')
复制代码


对应 accessibility id 定位器的代码如下:

driver.find_element_by_assessibility_id("ContentDescription")
复制代码


Java 版本

driver.findElementByCssSelector("*[description=\"ContentDescription\"]");
复制代码


对应 accessibility id 的定位器代码如下:

driver.findElementByAccessibilityId("ContentDescription");
复制代码

搜索微信公众号:TestingStudio 霍格沃兹的干货都很硬核

用户头像

社区:ceshiren.com 2022-08-29 加入

微信公众号:霍格沃兹测试开发 提供性能测试、自动化测试、测试开发等资料、实事更新一线互联网大厂测试岗位内推需求,共享测试行业动态及资讯,更可零距离接触众多业内大佬

评论

发布
暂无评论
软件测试 | 高级定位技巧_测试_测吧(北京)科技有限公司_InfoQ写作社区