Appium笔记4--滑动屏幕操作及UIAutomator介绍

appium提供的滑动屏幕方法

# convenience method added to Appium (NOT Selenium 3)
def swipe(self, start_x, start_y, end_x, end_y, duration=None):
   
"""Swipe from one point to another point, for an optional duration.

    :Args:
     - start_x - x-coordinate at which to start
     - start_y - y-coordinate at which to start
     - end_x - x-coordinate at which to stop
     - end_y - y-coordinate at which to stop
     - duration - (optional) time to take the swipe, in ms.

    :Usage:
        driver.swipe(100, 100, 100, 400)
    """

用法:driver.swipe(200, 500,1000, 500,  duration=500)

参数就是起点和终点x/y坐标

duration是滑动从起点到终点坐标所耗费的时间,单位是毫秒。

注意这个时间非常重要。正常速度滑动和快速滑动的效果是不一样的

 

这样用swipe同样存在的问题就是,兼容性不行。

如果换了屏幕,可能会有问题,比如有的屏幕是分辨率更低的,没有1000y坐标。就出问题了。

 

可以根据元素宽度和左上角坐标来计算出相对坐标

方法是先获:

ele = driver.find_element_by_id('com.huawei.appmarket:id/commodityLL')
location=ele.location#左上角坐标
size=ele.size#元素的高度和宽度

#计算起始点坐标
start_x=location['x']+int(size['width'])*0.2
start_y=location['y']+int(size['height'])*0.5
end_x=location['x']+int(size['width'])*0.8
end_y=location['y']+int(size['height'])*0.5

 

TIPS:可能会遇到的取元素的宽度为负数的问题

比如print(ele.size)

结果:{'height': 672, 'width': -24},返回的宽度为负数,显然不对

经查询,这是底层返回的结果,可能是改应用不支持某个底层参数

解决方案:

desired_caps['automationName'] = 'uiautomator2'

修改底层测试库配置为'uiautomator2'

这个应该是appium优化过的底层库,修改了一些BUG,因此大家在驱动手机app遇到一些异常情况,可以考虑使用此方法,如果不设置,默认用的就是'uiautomator'(可能会有些问题)

 

==============================================================

 

UI Automator介绍

关于uiauomator详细信息,有条件科学上网的可以打开官方文档:

UIAutomator官方网址

---------------------------------------------------------------------------------------------------------------------------------------------

appium是通过一些底层框架来控制设备的,比如安卓设备是通过UIautomator

我们学习的选择 界面元素的方式,根据id,classname, accessibilityid,xpath,

这些方法,其实底层都是利用了 uiautomator的API功能实现的

看图:

Appium笔记4--滑动屏幕操作及UIAutomator介绍

 

手机上bootstrap.jar通过调用uiautomator 中的api来完成自动化操作

---------------------------------------------------------------------------------------------------------------------------------

以下来自官方原文:

UI Automator 测试框架提供了一组 API 来构建 UI 测试,用于在用户应用和系统应用中执行交互。利用 UI Automator API,您可以执行在测试设备中打开设置菜单或应用启动器等操作。UI Automator 测试框架非常适合编写黑盒自动化测试,其中的测试代码不依赖于目标应用的内部实现详情。

UI Automator 测试框架的主要功能包括:

  • 用于检查布局层次结构的查看器。如需了解详细信息,请参阅 UI Automator 查看器
  • 在目标设备上检索状态信息并执行操作的 API。如需了解详细信息,请参阅访问设备状态
  • 支持跨应用 UI 测试的 API。如需了解详细信息,请参阅 UI Automator API

要求 Android 4.3API 级别 18)或更高版本。

 

UI Automator 查看器

uiautomatorviewer 工具提供了一个方便的 GUI,可以扫描和分析 Android 设备上当前显示的 UI 组件。您可以使用此工具检查布局层次结构,并查看在设备前台显示的 UI 组件属性。利用此信息,您可以使用 UI Automator(例如,通过创建与特定可见属性匹配的 UI 选择器)创建控制更加精确的测试。

uiautomatorviewer 工具位于 <android-sdk>/tools/ 目录中。

访问设备状态

UI Automator 测试框架提供了一个 UiDevice 类,用于在目标应用运行的设备上访问和执行操作。您可以调用其方法来访问设备属性,如当前屏幕方向或显示尺寸。UiDevice 类还可用于执行以下操作:

  • 更改设备旋转
  • D-pad 按钮
  • 返回主屏幕菜单按钮
  • 打开通知栏
  • 对当前窗口进行屏幕截图

例如,要模拟按下主屏幕按钮,请调用 UiDevice.pressHome() 方法。

UI Automator API

利用 UI Automator API,您可以编写稳健可靠的测试,而无需了解目标应用的实现详情。您可以使用这些 API 在多个应用中捕获和操作 UI 组件:

  • UiCollection:枚举容器的 UI 元素以便计算子元素个数,或者通过可见的文本或内容描述属性来指代子元素。
  • UiObject:表示设备上可见的 UI 元素。
  • UiScrollable:为在可滚动 UI 容器中搜索项目提供支持。
  • UiSelector:表示在设备上查询一个或多个目标 UI 元素。
  • Configurator:允许您设置运行 UI Automator 测试所需的关键参数。

 

其中UiSelector是我们appium自动化代码选择元素时候直接使用到的

 

关于UiSelector官方文档介绍:

https://developer.android.google.cn/reference/android/support/test/uiautomator/UiSelector

 

Specifies the elements in the layout hierarchy for tests to target, filtered by properties such as text value, content-description, class name, and state information. You can also target an element by its location in a layout hierarchy.

官方解释:用来生成一个定位器来选择界面中的控件元素,可以通过text,content-desc,class,和一些状态信息来进行条件过滤。

 

UiSelector类似于 appium find_element_by_xxx()方法中函数值

 

比如根据ID选择元素

Java语法:new UiSelector().resourceId(“io.manong.developerdaily:id/tv_tab_title”)

 

appium用法:driver.find_element_by_android_uiautomator('new UiSelector().resourceId("io.manong.developerdaily:id/tv_tab_title")')
 

注意,Java语法中用双引号来表示字符串,所以python代码中参数要用单引号或者三引号

如果不懂 java语法,除去最前面的 new ,后面的写法和python比较类似。

new是java里面实例化对象的关键字

 

 

根据ClassName选择元素

Java语法:new UiSelector().className("android.widget.TextView")

 

appium用法:

driver.find_element_by_android_uiautomator('new UiSelector().className("android.widget.TextView")')

规律:

driver.find_element_by_android_uiautomator(UIAutomator Selector)

driver.find_elements_by_android_uiautomator(UIAutomator Selector)

 

UIAutomator SelectorUIAutomator选择表达式,类似于xpath会返回一个或多个结果

 

关于UiSelector可以通过哪些规则来寻找元素,方法有

 

className(String className)

根据class名称

 

classNameMatches(String regex)

根据class名称的正则表达式

 

description(String desc)

根据content-desc

 

descriptionContains(String desc)

根据 content-desc中包含的字符串

 

text(String text)

根据文本值

 

textContains(String text)

根据文本值包含的字符串

 

基本上除了xpath之外,可以通过appium实现的找元素方式,UIAutomator也有,因为底层就是靠他实现的

 

xpath虽然没有直接对应的方法,但是像xpath

这种// 表示后代关系的,

这种x[n]表示第几个子节点的,

UIAutomator却有对应的方式,

 

childSelector(UiSelector selector)

用来选择后代元素(可以是非直接子元素),对应//

 

index(int index)

index表示其父元素的几个节点,类似xpath 里面的*[n]

 

instance(int instance)

匹配的结果所有元素里面的第几个元素,和是不是父元素的第几个元素没有关系

比如通过// android.widget.TextView

找到了十个对应类型的元素,instance(1) 表示第二个对应的元素,下标是从0开始的。