【Python】AppUI自动化—appium自动化元素定位、元素事件操作(17)下

文章目录

  • 前言
  • 一.Appium 元素定位
    • 1.定位方式种类
    • 2.如何定位
      • 2.1 id定位
      • 2.2 className定位
      • 2.3 content-desc 定位
      • 2.4 Android Uiautomator定位
        • 4.1 text定位
        • 4.2 text模糊定位
        • 4.3 text正则匹配定位
        • 4.4 resourceId定位
        • 4.5 resourceId正则匹配定位
        • 4.6 className定位
        • 4.7 className正则匹配定位
        • 4.8 组合定位
      • 2.5 xpath定位
        • 5.1 唯一属性定位
        • 5.2 模糊匹配定位
        • 5.3 组合定位
        • 5.4 层级定位
      • 2.6.IOS定位
      • 2.7.元素等待
      • 2.8.注意点
  • 二.Appium 基础Api
  • 三.Appium 基础操作
  • 四.Appium 键盘操作
    • 1.模拟输入
    • 2.模拟按键
    • 3.模拟点击
  • 五.Appium 触摸操作
    • 1.TouchAction
    • 2.MultiAction(多点触控 放大缩小操作)
    • 3.滑屏操作(swipe、scroll、drag_and_drop)
      • 3.1.屏幕滑动函数
      • 3.2.屏幕滑动python脚本
  • 六.其他操作
    • 1.Toast信息获取
    • 2.操作手机通知栏

前言

  • 想要使用appium元素定位,需搭建想要的开发测试环境,没有搭建环境的小伙伴详见上文
    【Python】AppUI自动化—appium自动化开发环境部署、APP测试案例(17)上

一.Appium 元素定位

定位原理

  • 使用Python或Java调用相关的Client,那么Appium里就会通过Webdriver协议(Selenium里同样)在应用层进行HTTP方式的数据请求,收到请求的手机上Appium APPServer就会解析相关的请求并且使用Appium提供的相应自动化测试方法去驱动手机做出相应的操作。

1.定位方式种类

导入库

from appium.webdriver.common.appiumby import AppiumBy

目前,Appium 支持的定位方式,如下所示:

cssSelector              Selenium 最强大的定位方法,比 xpath 速度快,但比 xpath 难上手
linkText                 链接元素的全部显示文字
partialLinkText          链接元素的部分显示文字
name                     元素的 name 属性,目前官方在移动端去掉这个定位方式,使用 AccessibilityId 替代
tagName                  元素的标签名
className                元素的 class 属性
id                       元素的 id 属性(resource-id)
xpath                    比 css 定位方式稍弱一些的定位方法,但胜在容易上手,比较好使用,缺点就是速度慢一些。
AccessibilityId          Appium 中用于替代 name 定位方式
AndroidUIAutomator       Android 测试,最强大速度最快的定位方式
iOSNsPredicateString     iOS 谓词的定位方式,仅支持 XCTest 框架,需大于 iOS 9.3或以上
IosUIAutomation          iOS 谓词的定位方式,仅支持 UIAutomation 框架,需大于 iOS 9.3或以下
IOSClassChain            国外大神 Mykola Mokhnach 开发类似 xpath 的定位方式,仅支持  XCTest 框架,,不如 xpath 和 iOSNsPredicateString 好
windowsAutomation        windows 应用自动化的定位方式
  • 上述所示的定位方式中,name由于官方的原因废弃掉,所以不在这里赘述了。tagName、linkText 和 partialLinkText 在我的理解中,一般是在 web 页面使用,移动端很少用。

2.如何定位

2.1 id定位

  • id或者叫resource-id,一般来说是唯一值,使用Inspector就可以定位到,查到值之后可以使用搜索查看下是否唯一。

    • 支持:Android,仅支持 Android 4.2或以上,推荐使用

在这里插入图片描述
在这里插入图片描述

from appium import webdriver
from base.base_driver import driver_setup
from appium.webdriver.common.appiumby import AppiumBy

driver_setup ={}#必填参数
driver = webdriver.Remote('http://localhost:4723/wd/hub', driver_setup)
# find_element_by_xxxxx 此类方法已弃用,需使用AppiumBy中的各类元素定位方法即可。
driver.find_element_by_id('com.tiffany.rta.debug:id/edt_customer_name')
# find_element用此方法
driver.find_element(AppiumBy.ID('com.tiffany.rta.debug:id/edt_customer_name'))
  • android中两个id的区别
    • accessibility_id就是元素属性里面的content-desc,不是每个元素都有这个属性、id就是对应元素的resource-id属性值

2.2 className定位

  • className一般用来决定元素的类型属性,但不推荐使用,界面中相同类型的元素重复的几率较高,无法快速定位到所需要的元素,使用率较低。
    • 支持:Android 和 iOS

在这里插入图片描述

driver.find_element(AppiumBy.CLASS_NAME('android.widget.EditText'))

2.3 content-desc 定位

  • 这个是用来描述当前元素的功能的,类似于备注。但绝大多数情况下,除非硬性规定,这个属性值一般为空所以实用性不高。

    driver.find_element(AppiumBy.ACCESSIBILITY_ID('这是一个按钮'))
    

2.4 Android Uiautomator定位

  • Android特有的定位方式,原理是通过android自带android uiautomator的类库递归搜索元素,比appium的定位方式更多以及更适用,也支持id、className、text、模糊匹配等进行定位。
    • 仅支持 Android 4.2或以上
4.1 text定位

在这里插入图片描述

driver.find_element(AppiumBy.ANDROID_UIAUTOMATOR, 'new UiSelector().text("请输入顾客姓名")')
4.2 text模糊定位
  • 定位text较长的元素时,就可以使用模糊匹配的方法textContains来进行元素的定位。
driver.find_element(AppiumBy.ANDROID_UIAUTOMATOR, 'new UiSelector().textContains("姓名")')
4.3 text正则匹配定位
driver.find_element(AppiumBy.ANDROID_UIAUTOMATOR, 'new UiSelector().textMatches("^请输入.*")')
4.4 resourceId定位
find_element(AppiumBy.ANDROID_UIAUTOMATOR, 'new UiSelector().resourceId("com.tiffany.rta.debug:id/edt_customer_name")')
4.5 resourceId正则匹配定位
driver.find_element(AppiumBy.ANDROID_UIAUTOMATOR, 'new UiSelector().resourceIdMatches(".+edt_customer_name")')
4.6 className定位
driver.find_element(AppiumBy.ANDROID_UIAUTOMATOR, 'new UiSelector().className("android.widget.EditText")')
4.7 className正则匹配定位
driver.find_element(AppiumBy.ANDROID_UIAUTOMATOR, 'new UiSelector().classNameMatches(".*EditText")')
4.8 组合定位
# id与text组合
driver.find_element(AppiumBy.ANDROID_UIAUTOMATOR, 'new UiSelector().resourceId("com.tiffany.rta.debug:id/edt_customer_name").text("顾客名称")')

# className与text组合
driver.find_element(AppiumBy.ANDROID_UIAUTOMATOR, 'new UiSelector().className("android.widget.EditText").text("顾客名称")')

2.5 xpath定位

XPath 是一门在 XML 文档中查找信息的语言。XPath 可用来在 XML 文档中对元素和属性进行遍历

  • 这种定位方式是比较万能的,但万能是相对的,如果在前几种都不太好定位的情况下,我们推荐使用xpath定位方式,只不过极度不推荐使用绝对路径的定位方式大量的绝对路径定位方式会使脚本或框架在后期的维护上造成很大的难度与较高的成本。所以如果要使用xpath定位方法就比较推荐以下几种方法。
    • 支持:Android 和 iOS。但由于 iOS 10开始使用的 XCUITest 框架原生不支持
5.1 唯一属性定位
  • 如果页面中属性的text或id是固定且唯一的,可以使用以下方法。

    # text属性唯一
    driver.find_element(AppiumBy.XPATH('//*[@text="顾客名称"]'))
    
    • 这里的 // 指的是相对路径* 代表匹配所有@ 是查找对应的指定属性,这里是通过text来定位的所以就在@后面填写text,之后跟上具体的属性值即可。
    # id属性唯一
    
    # class属性唯一
    driver.find_element(AppiumBy.XPATH('//*[@class="android.widget.EditText"]'))
    
5.2 模糊匹配定位
  • text中的模糊匹配类似,是在不太清楚具体xpath路径时具体值可能变动的情况下快速定位匹配的方法。

    # 以text属性为例,class、id方法类似
    driver.find_element(AppiumBy.XPATH('//*[contains(@text="新增")]'))
    
5.3 组合定位
  • 顾名思义,一个元素的多个元素可以通过xpath同时进行指定惊喜感定位。

    # id和text属性
    driver.find_element(AppiumBy.XPATH('//*[@resource-id="com.tiffany.rta.debug:id/edt_customer_name" and @text="顾客名称"]'))
    
    • 其他的组合以此类推
5.4 层级定位
  • 如果出现某一个元素基本没有什么属性值,往往只有一个重复属性的时候,我们可以使用层级定位的方式来帮助我们进行快速定位元素。无论层级是从上到下还是从下到上(父子)只需要按照你指定的顺序进行编写就行。
# 通过某一个元素搜索下级元素或上级元素
driver.find_element(AppiumBy.XPATH('//*[@resource-id="com.tiffany.rta.debug:id/edt_customer_name"]/android.widget.EditText'))

2.6.IOS定位

iOSNsPredicate

  • 仅支持 iOS 10或以上,可支持元素的单个属性和多个属性定位,推荐使用。

    AppiumBy.IOS_PREDICATE("type == 'XCUIElementTypeButton'")    # 使用一种属性定位
    AppiumBy.IOS_PREDICATE("type == 'XCUIElementTypeButton' AND label == '更多信息'")    # 使用两种属性定位
    

iOSClassChain

  • 仅支持 iOS 10或以上,这是 github 的 Mykola Mokhnach 大神开发,仅限在 WebDriverAgent 框架使用,用于替代 xpath 的,但使用一阵子后,感觉灵活性没有 xpath 和 iOSNsPredicate 好,应该还不完善吧。具体使用方法,请见:iOSClassChain。

    AppiumBy.IOS_CLASS_CHAIN('XCUIElementTypeWindow[1]/XCUIElementTypeOther[1]/XCUIElementTypeOther[1]/XCUIElementTypeNavigationBar[1]/XCUIElementTypeOther[1]/XCUIElementTypeButton[2]')
    

IosUIAutomation

  • 仅支持 iOS 9.3或以下,是 iOS 旧框架 UIAutomation 的定位方式,这个定位类型同样可使用 iOS 谓词进行定位,详细可参考:iOSNsPredicate

    AppiumBy.IOS_UIAUTOMATION("type == 'UIAButton'")     # 使用一种属性定位
    AppiumBy.IOS_UIAUTOMATION("type == 'UIAButton' AND label == '更多信息'")    # 使用两种属性定位
    

2.7.元素等待

# 第一种:固定延迟 5s
import time
time.sleep(5)
# 第二种:隐形等待 如果等到了进程马上运行,如没有等到,10秒后报错
from appium import webdriver
from appium.webdriver.common.appiumby import AppiumBy

# 启动Chrome驱动
desired_caps = {}
driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub', desired_caps)
driver.implicitly_wait(10) # 在启动后到启动结束所有进程都保持10S处理时间。
# 第三种:显形等待
# 明确等待某个条件的满足之后,再去执行下一步的操作。
# 程序每隔XX秒看一眼,如果条件成立了,则执行下一步,否则继续等待,直到超过设置最长时间,然后抛出TimeoutException。

# 使用之前,引入相关的库
from appium import webdriver
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from appium.webdriver.common.appiumby import AppiumBy
from appium.webdriver.common.mobileby import MobileBy

# WebDriverWait类:显性等待类
# WebDriverWait(driver,等待时常,轮询周期).until()条件/until_not()直到条件不成立


# 以下是显性等待使用方法:
# 1、先确认元素的定位表达式
s_id = 'TANGRAM__PSP_11__regLink'

# 2、设置显性等待 WebDriverWait(driver,等待时常:10S,轮询周期:默认值0.5S).until()/until_not():条件成立/直到条件不成立
WebDriverWait(driver, 10).until(EC.presence_of_element_located((AppiumBy.ID, s_id)))  # 条件 (元素定位为的类型,元素定位的表达式)

# 3、使用后续的方法 比如:点击
driver.find_element(AppiumBy.ID, 'TANGRAM__PSP_11__regLink').click()
  • 附:常用的 expected_conditions 模块下的条件:
# EC.presence_of_element_located():元素存在
# EC.visibility_of_element_located():元素可见
# EC.element_to_be_clickable():元素可点击
# EC.new_window_is_opened()  # 新窗口是否打开
# EC.frame_to_be_available_and_switch_to_it()  # 可用并且切换进去
# EC.alert_is_present()  # 弹出框的出现
# EC.element_selection_state_to_be()  # 下拉列表状态
# EC.element_to_be_selected()  # 某一个定位表达式的值应该是被选中的
# EC.element_selection_state_to_be()  # 定位表达式的选中状态是什么
# EC.element_to_be_selected()  # 元素可用被选中的
# EC.invisibility_of_element()  # 隐形的元素
# EC.number_of_windows_to_be()  # 窗口的个数应该为
# # EC.presence_of_all_elements_located()  # 所有元素应该都存在
# EC.text_to_be_present_in_element()  # 元素出现的文本内容
# EC.text_to_be_present_in_element_value()  # 元素出现的文本内容值
# EC.url_changes()  # url的改变
# EC.url_contains()  # url的包含
# EC.url_matches()  # url的匹配
# EC.url_to_be()  # url的应该是什么

2.8.注意点

  1. 如果同一页面中某一属性有多个元素时,可以使用定位方法+下标来指定想要操作的元素,并且需要注意含有多个元素时要使用find_elements函数。

    # 定义输入框,画面中共有3个输入框
    element = driver.find_elements(AppiumBy.CLASS_NAME('android.widget.EditText'))
    # 指定第一个输入框中输入"张三"
    element[0].send_keys("张三")
    
  2. Android与iOS中元素定位的差异点在于,Android的元素如果不在当前设备画面中,比如需要上划或者下划屏幕(swipe)能看见的元素,需要先做对应操作让其展示出后才能进行元素的定位。而iOS则完全不需要如此操作 (注意)

  3. 即使是id也不会绝对唯一,一般来说如果脚本或框架出定位了id属性却出现NoSuchElementException就需要查看属性是否重复且选择了错误的元素。所以建议在定位元素前多用用Inspector中的元素搜索功能查看一下

  4. 如果你是做iOS相关的APP自动化的话,尽量在元素定位的时候少用xpath方法来定位,即使是相对路径的方式也仍然会大大增加Appium的运行时间;

  5. 如果某些元素是需要异步加载,在定位元素前建议加上等待时间,强制等待不太推荐,至于隐性还是显性的大家结合着自己的测试业务与被测对象看着来就行。

二.Appium 基础Api

driver.start_activity(appPackage, appActivity)  启动应用
#appPackage:要打开的程序的包名  appActivity:要打开的程序的界面名
#说明:appium⽀持跨应⽤,可以在操作应⽤中切换到B应⽤。2.9.0废弃
driver.activate_app(appPackage) 				 如果没有启动,就启动该应用:

driver.current_package 						获取当前所在应用包名
driver.cuIrrent_activity 						获取当前所在应用启动名
driver.close_app()								关闭APP
driver.quit()									关闭驱动

driver.install_app(app_path)     				安装app(app_path:apk文件路径)
driver.remove_app(app_id)						卸载app(app_path=appPackageapk文件包名)
driver.is_app_installed(app_id 				app是否安装(app_path=appPackageapk文件包名)

background_app(seconds)						置于后台

三.Appium 基础操作

引入对象

from appium.webdriver.common.appiumby import AppiumBy
点击操作 也可以用tab()实现点击操作
driver.find_element(AppiumBy.ID, "resource-id的值").click()

输入框内输入内容
driver.find_element(AppiumBy.ID, "resource-id的值").send_keys("test content")
清空输入框内容
driver.find_element(AppiumBy.ID, "resource-id的值").clear()

获得元素的text内容
print(driver.find_element(AppiumBy.ID, "resource-id的值").text)
返回元素的文本值
driver.find_element(AppiumBy.ID, "resource-id的值".get_attribute("class")
获取元素的大小(高和宽)
driver.find_element(AppiumBy.ID, "resource-id的值").size
获取元素左上角的坐标
driver.find_element(AppiumBy.ID, "resource-id的值").location

获取手机的分辨率 {'width': 1080, 'height': 2252}
driver.get_window_size() 
 获取当前页面的源码
driver.page_source

将手机屏幕截图并保存电脑上的文件
driver.get_screenshot_as_file("文件存储的电脑路径")

打系统通知栏(仅支持API 18 以上的安卓系统)
driver.open_notifications()

四.Appium 键盘操作

1.模拟输入

往文本框就用到send_keys()函数。

driver.find_element(AppiumBy.ID, "resource-id的值").send_keys("输入内容")
  • 如果要输入中文的话,需要在Desired Capabilities中加入'unicodeKeyboard': True'resetKeyboard': True这两项参数;它们分别代表可以以unicode编码格式进行输入、初始化键盘状态。

2.模拟按键

  • 另一种则是需要通过真实的按键或手机虚拟键盘进行输入框或交互框的测试数据输入,我们可以使用扩展方法press_keycode()注意此函数只适用于Android

    driver.press_keycode(keycode, metastate=None)  
    #keycode是发送给设备的关键代码,metastate是关键代码的元信息,一般是默认值。
    
  • 例如:发送手机按键到设备

    • 模拟按 "返回键" "home键" 等等操作,很多应用有按2次返回键退出应用的功能,

      	"""
      	点击三次音量加,等待 3S,再点击三次音量减。
      	"""
      	# 按音量 + 三次
      	for i in range(3):
      	    driver.press_keycode(24)
      	    time.sleep(1)
      	
      	time.sleep(3)
      	# 按音量 - 三次
      	for i in range(3):
      	    driver.press_keycode(25)
      
    • send_keys()不同,在使用模拟按键时,需要先将焦点放置于所需要交互的控件上。

      driver.find_element(AppiumBy.ID,"resource-id的值").click()
      

这里区分为两种键盘

  • 一种是模拟手机的物理按键(菜单、Home、返回等), 另一种是模拟键盘按键。分别对应driver.keyevent(keycode)driver.press_keycode(keycode)两种函数。

    #物理按键:手机真实按键,如菜单、Home、返回、音量按键
    driver.keyevent(keycode)        keycode填入的是手机物理按键的数字代号(菜单、Home、返回)
    #键盘按键:1-9、26个字符、上下左右、回车、ctrl等存在于键盘上面的按键
    driver.press_keycode(keycode)      keycode填入的是键盘按键的数字代号
    

    键盘按键数字代号
    在这里插入图片描述

    • 另外需要模拟长按某些物理按键的话(长按电源、长按音量),就可以使用long_press_keycode(keycode)函数来进行操作。

    键盘按键数字代号

    • 控制按键
      在这里插入图片描述

    • 基本按键
      在这里插入图片描述

3.模拟点击

  • 除了click()以外,我们还可以使用tap()对一个元素或特定坐标进行点击操作。

    driver.tap([(100, 200)], 500)
    
    • 表示根据屏幕坐标来进行点击的,坐标用元组表示并且最多可以有5组坐标,分别代表五个触点(表示五个手指)
    • 最外部用列表来进行表示。列表后面的数字代表操作停留的时间,以毫秒为单位。
      • 由于使用坐标来进行操作,各类手机屏幕大小有所不同,坐标常常会发生偏移,导致定位失败,所以不推荐使用

五.Appium 触摸操作

  • 引入对象
    from appium.webdriver.common.appiumby import AppiumBy
    from appium.webdriver.common.touch_action import TouchAction
    

1.TouchAction

  • TouchAction对象包含 tab (点击)、press(短按)、move_to(滑动到某个坐标)等方法
    • 通过TouchAction对象,添加tap、move_to等操作,然后perform()执行,可以实现解锁屏幕等功能
    • 规范中的可用事件有:
      短按 (press)  释放 (release)  移动到 (moveTo)
      点击 (tap)  等待 (wait)  长按 (longPress)
      取消 (cancel)  执行 (perform)
      
  1. 点击(轻敲)操作driver.tap(坐标x,坐标y, 持续点击时间/s)

    #第1种:坐标定位实现点击(不推荐)
    TouchAction(driver).tap(x=155, y=706, count=1).perform()
    #第2种:指定元素实现点击(推荐)
    TouchAction(driver).tap(ele, count=1).perform()
    
  2. 多次滑屏:建议少用坐标定位 下面只是举例子

    from appium.webdriver.common.touch_action import TouchAction
    # 短按之后要释放 长按之后也是需要释放的。
    action=TouchAction(driver)
    action.press(x=220,y=700).move_to(x=840, y=700).move_to(x=220, y=1530).move_to(x=840, y=1530).release().perform()
    
    • 2.1. 解锁微信服务里面九宫格例子:

      import time
      from selenium.webdriver.support.wait import WebDriverWait
      from selenium.webdriver.support import expected_conditions as EC
      from appium import webdriver
      from appium.webdriver.common.mobileby import MobileBy
      from appium.webdriver.common.touch_action import TouchAction
      
      desired_caps = {
          'platformName': 'Android',
          'platformVersion': '8.1',
          'deviceName': 'ye_shen_Android',
          'appPackage': 'com.tencent.mm',
          'appActivity': 'com.tencent.mm.ui.LauncherUI',
          'noReset': True,
          'autoAcceptAlerts': True,
          'newCommandTimeout': 240
      }
      
      driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub', desired_caps)
      driver.implicitly_wait(10)
      
      # 点击 微信 我的
      loc = (MobileBy.ANDROID_UIAUTOMATOR, 'new UiSelector().resourceId("com.tencent.mm:id/j5t")')
      WebDriverWait(driver, 30).until(EC.visibility_of_element_located(loc))
      TouchAction(driver).tap(x=540, y=1255).wait(200).perform()
      
      # 点击 服务
      locc = (MobileBy.ANDROID_UIAUTOMATOR, 'new UiSelector().text("服务")')
      WebDriverWait(driver, 30).until(EC.visibility_of_element_located(locc))
      ele = driver.find_element(MobileBy.ANDROID_UIAUTOMATOR, 'new UiSelector().text("服务")')
      TouchAction(driver).tap(ele).wait(200).perform()
      
      # 检查 请输入手势密码
      loccs = (MobileBy.ANDROID_UIAUTOMATOR, 'new UiSelector().text("请输入手势密码")')
      WebDriverWait(driver, 30).until(EC.visibility_of_element_located(loccs))
      
      # 获取起始坐标-九宫格左上顶点
      loc = driver.find_element(MobileBy.ID, "com.tencent.mm:id/hrs").location
      print(loc)
      # 获取九宫格元素大小 height width 宽 和 高
      loc_size = driver.find_element(MobileBy.ID, "com.tencent.mm:id/hrs").size
      print(loc_size)
      
      # 获取分割后的均值,即下面要用到的九宫格的步长
      step = loc_size["width"] / 6
      step_x = loc_size["width"] / 6
      step_y = loc_size["height"] / 6
      
      # 计算出每个点的坐标
      point1 = (loc["x"] + step, loc["y"] + step * 5)
      point2 = (point1[0], point1[1] - step * 2)
      point3 = (point2[0], point2[1] - step * 2)
      point4 = (point3[0] + step * 2, point3[1] + step * 2)
      point5 = (point4[0] + step * 2, point4[1] + step * 2)
      point6 = (point5[0], point5[1] - step * 2)
      point7 = (point6[0], point6[1] - step * 2)
      
      
      # 进行滑动操作
      TouchAction(driver).press(x=point1[0], y=point1[1]).wait(500). \
          move_to(x=point2[0], y=point2[1]). \
          move_to(x=point3[0], y=point3[1]). \
          move_to(x=point4[0], y=point4[1]). \
          move_to(x=point5[0], y=point5[1]). \
          move_to(x=point6[0], y=point6[1]). \
          move_to(x=point7[0], y=point7[1]). \
          release().perform()
      
      time.sleep(10)
      driver.quit()
      
    • 如图
      在这里插入图片描述

2.MultiAction(多点触控 放大缩小操作)

背景:使用地图App、图片放大缩小场景需要对界面进行缩放操作来更加便利的查看位置或者图片放大操作。

  1. 根据解析手势操作放大缩小

    • 在 Appium 里面提供了 MultiAction 类来进行放大、缩小操作。模拟真实手指操作
      在这里插入图片描述
  2. MultiAction多点触控的类,可以模拟用户多点操作。主要包含 add()perform()两个方法, MultiAction可以结合前面所学的 ActionTouch可以模拟出用户的多个手指滑动的操作效果。

    • 引入模块
      from appium.webdriver.common.multi_action import MultiAction
      from appium.webdriver.common.touch_action import TouchAction
      
      实现代码
      #元素1移动到元素2
      a1 = TouchAction(driver)
      a1.press(el1).move_to(el2).release()
      #元素2移动到元素1
      a2 = TouchAction(driver)
      a2.press(el2).move_to(el1).release()
      
      MultiAction(driver).add(a1, a2).perform()
      

3.放大/缩小操作另一个方法:zoom/pinch

zoom(self, element=None, percent=200, steps=50)
pinch(self, element=None, percent=200, steps=50)
#percent:在某控件上执行放大操作,默认放大比例为200%
#steps:表示 放大/缩小 动作分多少步完成,默认50
# 放大
driver.zoom(element)
# 缩小
driver.pinch(element)

3.滑屏操作(swipe、scroll、drag_and_drop)

3.1.屏幕滑动函数

  1. driver.swipe(x1, y1, x2, y2,duration)

    • swipe(起始X,起始Y, 结束X,结束Y)
      • 起始X 结束X:X滑动的距离
      • 起始Y - 结束Y:Y滑动的距离
    • 从坐标(x1,x2)滑动到坐标(x2,y2),duration:时长/毫秒,滑动时间(滑动的坐标不能超过屏幕的宽高)
  2. driver.scroll(self,original_el,destination_el)

    • 从一个元素滚动到另一个元素,只能是两个元素之间的滑动。
    • 参数:
      • origin_el - 要滚动的起始元素
      • destination_el - 要滚动到的结束元素
      • duration - 持续时间,单位毫秒,默认为 600 ms
    • 注意:操作过程有 惯性,需要添加duration参数,参数值越大,惯性越小。
  3. driver.drag_and_drop(self, origin_el: WebElement, destination_el: WebElement)

    • 从一个元素拖曳到另一个元素,第二个元素代替第一个元素原本屏幕上的位置。
    • 参数:
      • origin_el - 要滑动页面的起始元素
      • destination_el - 要滑动页面到结束元素。
    • driver.drag_and_drop 方法说明:不能设置持续时间,没有惯性。

区别:

  • 滑动和拖拽无非就是考虑是否具有"惯性",以及传递的参数是"元素"还是"坐标"。
    • scroll:有 “惯性” ,传入 “元素”,可以通过设置duration参数来进行控制惯性大小
    • drag_and_drop:无 “惯性” ,传入 “元素”
    • swipe:有 “惯性” ,传入 “坐标”,可以通过设置duration参数来进行控制惯性大小

3.2.屏幕滑动python脚本

以 swipe为例,屏幕上下左右滑动的方法

from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from appium import webdriver
from appium.webdriver.common.mobileby import AppiumBy

"""
滑动测试 swipe
"""
# 初始化参数
desired_caps = {
    'platformName': 'Android',  # 被测手机是安卓
    'platformVersion': '9',  # 手机安卓版本
    "deviceName": "FJH7N19131000457",
    'appPackage': 'com.huawei.appmarket',  # 启动APP Package名称
    'appActivity': 'com.huawei.appmarket.MarketActivity',  # 启动Activity名称
    'unicodeKeyboard': True,  # 使用自带输入法,输入中文时填True
    'resetKeyboard': True,  # 执行完程序恢复原来输入法
    'noReset': True,  # 不要重置App,如果为False的话,执行完脚本后,app的数据会清空,比如你原本登录了,执行完脚本后就退出登录了
    'newCommandTimeout': 6000,
    'automationName': 'UiAutomator2',
    'skipServerInstallation': True
}

driver = webdriver.Remote('http://127.0.0.1:4723', desired_caps)

loc = (AppiumBy.ID, 'com.huawei.gamebox:id/hiappbase_search_layout_id')
WebDriverWait(driver, 10).until(EC.visibility_of_element_located(loc))


# 获得屏幕大小宽和高
def getSize(driver):
    x = driver.get_window_size()['width']
    y = driver.get_window_size()['height']
    return (x, y)


# 屏幕向上滑动
def swipeUp(driver, t=1000):
    l = getSize(driver)
    x1 = int(l[0] * 0.5)  # x坐标
    y1 = int(l[1] * 0.75)  # 起始y坐标
    y2 = int(l[1] * 0.25)  # 终点y坐标
    driver.swipe(x1, y1, x1, y2, t)


# 屏幕向下滑动
def swipeDown(driver, t=1000):
    l = getSize(driver)
    x1 = int(l[0] * 0.5)  # x坐标
    y1 = int(l[1] * 0.25)  # 起始y坐标
    y2 = int(l[1] * 0.75)  # 终点y坐标
    driver.swipe(x1, y1, x1, y2, t)


# 屏幕向左滑动
def swipLeft(driver, t):
    l = getSize(driver)
    x1 = int(l[0] * 0.75)
    y1 = int(l[1] * 0.5)
    x2 = int(l[0] * 0.05)
    driver.swipe(x1, y1, x2, y1, t)


# 屏幕向右滑动
def swipRight(driver, t=1000):
    l = getSize(driver)
    x1 = int(l[0] * 0.05)
    y1 = int(l[1] * 0.5)
    x2 = int(l[0] * 0.75)
    driver.swipe(x1, y1, x2, y1, t)

# 屏幕向下滑动2次
swipeUp(driver)
swipeUp(driver)

# 屏幕向上滑动2次
swipeDown(driver)
swipeDown(driver)

六.其他操作

1.Toast信息获取

Toast是Android中用来显示显示信息⼀种⿊底⽩字,有时间限制的提示信息,和Dialog不一样的是,Toast是没有焦点的,而且Toast显示的时间有限,过一定的时间就会自动消失。

  • Appium:1.6.3开始支持识别Toast内容 :v1.6.3起步
  • 比如:密码输错后,移动端的提示。即是Toast 信息
"""
    需求:
    1、获取网易新闻未同意协议进行登录  --> toast消息
    
    需求:打开《网易新闻》APP
    l、点击未登录菜单栏
    2、在未登录个人中心页面点击登录
    3、在一键登陆窗口点击微信登陆,并获取弹出提示信息
"""
 
 
# 点击未登录
driver.find_element_by_xpath("//*[@text='未登录']").click()
# 点击登录
driver.find_element_by_xpath("//*[@text='登录']").click()
# 点击微信登录
driver.find_element_by_xpath("//*[@text='微信登录']").click()
 
# 获取toast消息
msg = driver.find_element_by_xpath("//*[contains(@text,'请先勾选同意')]").text
print("toast消息为:",msg)

Toast封装:

def is_toast_exist(driver, ele, texts):
    # ele = (MobileBy.XPATH, '//*[contains(@text,"%s")]' % '密码错误')
    """
     - driver - 传driver
     - timeout - 最大超时时间,默认20s 设定为 10
     - poll_frequency  - 间隔查询时间,默认0.5s查询一次 设定为0.02S
     - ele 表达式
     - texts 属性
    :Usage:
     is_toast_exist(driver)
    """
    try:
        WebDriverWait(driver,10,0.02).until(EC.presence_of_element_located(ele))
        print(driver.find_element(MobileBy.XPATH,'//*[contains(@text,%s)]' % texts).text)
    except:
        print("没有匹配到toast!!!!!!!")

2.操作手机通知栏

  • 测试即时通信类软件的时候,如果收到其他人发送的一条消息,通知栏肯定会显示对应的消息。我们想通过通知栏来判断是否收到消息,一定要先操作手机的通知栏。

    driver.open_notifications():打开手机通知栏。
    
  • appium官方没有为我们提供关闭通知的Api,那么打开通知栏之后再怎么关闭呢,我们可以手指从下往上滑动或者按返回键。

    """
    打开通知栏,三秒后,关闭通知栏。
    """
    driver.open_notifications()
    time.sleep(3)
    #点击返回键
    driver.keyevent(4)
    #点击返回键
    driver.keyevent(4)
    

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/130503.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

QT项目|时间服务器架构

目录 一、 创建新UI界面的标题 二、 创建服务器运行图标 2.1 查找图标,并截图 2.2 加入QT资源库 三、编辑UI界面 3.1 根据要求,绘制UI界面 3.2 对控件进行命名 3.3 加入Group Box进行美化 四、 按钮操作设置 4.1 QT加入网络 4.2 转到槽&…

NetCore独立发布部署到Linux服务器

1、准备一台服务器 2核2G服务器足够 系统环境:Alibaba Cloud 3 或者其他版本的Linux操作系统都行 2、安装宝塔 yum install -y wget && wget -O install.sh https://download.bt.cn/install/install_6.0.sh && sh install.sh ed8484bec 安装后…

高德地图添加信息弹窗,信息弹窗是单独的组件

//弹窗组件 <template><el-card class"box-card" ref"boxCard" v-if"showCard"><div slot"header" class"clearfix"><div class"title">{{ model.pointName }}</div><div class…

Nacos使用指南

Nacos使用指南 1.认识Nacos Nacos是SpringCloudAlibaba的一个组件&#xff0c;遵循SpringCloud规范 2.Nacos的优势 1.支持服务端主动检测服务提供者状态。临时实例采用心跳检测&#xff0c;非临时实例采用主动检测 2.Nacos支持服务列表变更消息推送&#xff0c;消息更加及…

CCLink转Modbus TCP网关_CCLINK参数配置

CCLink转Modbus TCP网关&#xff08;XD-ETHCL20&#xff09;&#xff0c;具有CCLINK主从站功能。主要用途是将各种MODBUS-TCP设备接入到CCLINK总线中。它可以作为从站连接到CCLINK总线上&#xff0c;也可以作为主站或从站连接到MODBUS-MTP总线上。 1、 配置网关的CCLINK参数&am…

Docker 安装与优化

一、安装Docker 1、关闭防火墙 systemctl stop firewalld systemctl disable firewalld setenforce 02、安装依赖包 yum -y install yum-utils device-mapper-persistent-data lvm2#解释 yum-utils #提供了yum-config-manager工具 device mapper #是linux内核中支持逻辑卷…

阿里巴巴将开源720亿参数大模型;开源语言大模型演进史

&#x1f989; AI新闻 &#x1f680; 阿里巴巴将开源720亿参数大模型 摘要&#xff1a;在2023世界互联网大会乌镇峰会上&#xff0c;阿里巴巴集团CEO吴泳铭透露&#xff0c;阿里巴巴即将开源720亿参数大模型&#xff0c;这将是国内参数规模最大的开源大模型。目前&#xff0c…

华为eNSP实验-QinQ基本实验

1.拓扑图如下 PC1的设置如下&#xff1a; 在未配置VLAN之前&#xff0c;PC1可以ping通PC3&#xff0c;PC2可以ping通PC4&#xff08;因为同一网段&#xff09; 2.SW1和SW4配置VLAN <Huawei>system-view [Huawei]undo info-center enable //关闭提示信息 [Huawei]sysn…

基于springboot实现协同过滤算法商品推荐系统项目【项目源码】计算机毕业设计

基于springboot实现协同过滤算法商品推荐系统演示 Java语言简介 Java是由SUN公司推出&#xff0c;该公司于2010年被oracle公司收购。Java本是印度尼西亚的一个叫做爪洼岛的英文名称&#xff0c;也因此得来java是一杯正冒着热气咖啡的标识。Java语言在移动互联网的大背景下具备…

Pydantic:数据类型确认和解析神器

大家好&#xff0c;数据验证和解析是软件开发中的重要任务&#xff0c;特别是在处理用户输入或外部数据源时尤为重要&#xff0c;Python凭借其简洁性和多功能性&#xff0c;在这些任务中提供了各种库的帮助。在本文中将探讨Pydantic&#xff0c;介绍其特点&#xff0c;并提供一…

基于VPLC711的曲面外观检测XYR运动控制解决方案

市场应用背景 随着消费升级&#xff0c;产品形态正在朝着多样性和精细化方向迅速发展。这导致了对于复杂曲面轨迹加工的需求&#xff0c;包括外观检测、打磨抛光和点胶工艺控制&#xff0c;要求更高的精密度。企业必须主动满足市场需求&#xff0c;不断改进工艺&#xff0c;以…

「算法小记」-2:矩阵链相乘的方案数【迭代/递归/动态规划/区域化DP/记忆化搜索】(C++ )

&#x1f60e; 作者介绍&#xff1a;我是程序员洲洲&#xff0c;一个热爱写作的非著名程序员。CSDN全栈优质领域创作者、华为云博客社区云享专家、阿里云博客社区专家博主、前后端开发、人工智能研究生。公粽号&#xff1a;程序员洲洲。 &#x1f388; 本文专栏&#xff1a;本文…

RT-Thread系列09——ETH网口设备

文章目录 1. ETH测试第一步&#xff1a;cubemx配置。第二步&#xff1a;board.h配置。第三步&#xff1a;rtthread settings配置第四步&#xff1a;以太网复位引脚设置第五步&#xff1a;修改rtthread源码第六步&#xff1a;修改 cubemx 生成的 main 函数第七步&#xff1a;编译…

uniapp和vue3+ts开发小程序,使用vscode提示声明变量冲突解决办法

在uniapp中&#xff0c;我们可能经常会遇到需要在不用的环境中使用不同变量的场景&#xff0c;例如在VUE3中的小程序环境使用下面的方式导入echarts&#xff1a; const echarts require(../../static/echarts.min); 如果不是小程序环境则使用下面的方式导入echarts&#xff…

实战leetcode(二)

Practice makes perfect&#xff01; 实战一&#xff1a; 这里我们运用快慢指针的思想&#xff0c;我们的slow和fast都指向第一个节点&#xff0c;我们的快指针一次走两步&#xff0c;慢指针一次走一步&#xff0c;当我们的fast指针走到尾的时候&#xff0c;我们的慢指针正好…

vscode调试react 最初的源码

如果直接在react项目中打点调试, 调试的是 react-dom.development.js, 而源码里这些逻辑是分散在不同的包里的,如何才能够调试 React 最初的源码呢&#xff1f; JS 代码经过编译&#xff0c;会产生目标代码&#xff0c;但同时也会产生 sourcemap。sourcemap 的作用就是映射目…

为什么我一直是机器视觉调机仔,为什么一定要学一门高级语言编程?

​ 为什么我是机器视觉调机仔&#xff0c;为什么一定要学一门高级语言编程&#xff0c;以后好不好就业&#xff0c;待遇高不高&#xff0c;都是跟这项技术没关系&#xff0c;是跟这个技术背后的行业发展有关系。 你可以选择离机器视觉行业&#xff0c;也可以选择与高级语言相关…

[Mac软件]Adobe Media Encoder 2024 V24.0.2免激活版

软件说明 使用Media Encoder&#xff0c;您将能够处理和管理多媒体。插入、转码、创建代理版本&#xff0c;并几乎以任何可用的格式输出。在应用程序中以单一方式使用多媒体&#xff0c;包括Premiere Pro、After Effects和Audition。 紧密整合 与Adobe Premiere Pro、After …

SSL证书申请安全审核失败?

随着HTTPS普及&#xff0c;申请安装使用SSL证书成为了我们的必备项。但这个SSL证书申请过程中&#xff0c;遇到问题也是不少。今天我们来浅了解一下SSL证书为什么会出现安全审核失败&#xff1f; SSL证书申请会出现安全审核失败的情况可能是以下原因&#xff1a; 域名验证不通…

农业大棚智能化改造升级与远程视频监管方案,助力智慧农业建设发展

一、需求分析 随着现代化技术的发展&#xff0c;农业大棚的智慧化也成为当前备受关注的智慧农业发展手段。利用先进的信息化手段来对农业大棚进行管理&#xff0c;采集和掌握作物的生长状况、作业监督、生态环境等信息数据&#xff0c;实现精准操作、精细管理&#xff0c;远程…