【APP自动化基础】appium与设备交互方法
获取设备信息
获取设备大小
window_size = driver.get_window_size()
print(window_size) # {'width': 1080, 'height': 1920}
获取当前应用的信息
driver.current_activity # 获取当前应用的activity信息:.MainSettings
driver.current_package # 获取当前应用的package信息:com.android.settings
获取设备上下文信息(切换H5操作)
上下文:在程序中context我们可以理解为当前对象在程序中所处的一个环境。 比如前面提到的App一个界面是属于Activity类型,也就是Android界面环境,但是当访问内嵌的网页是属于另外一个环境(网页环境),两者处于不同的一个环境。
driver.contexts # 获取所有的上下文信息,返回值为列表类型
driver.context # 获取当前上下文,返回值为字符串类型
driver.current_context # 获取当前上下文,返回值为字符串类型
打印输出当前context,如果一直显示为Natvie App,则webview未开启
案例
import time
from appium import webdriver
from appium.webdriver.common.appiumby import AppiumBy
desired_caps = {
"platformName": "Android",
"platformVersion": "7.1.2",
"udid": "127.0.0.1:62001",
"appPackage": "com.xkw.client",
"appActivity": "com.zxxk.page.main.LauncherActivity",
"noReset": True,
'automationName': 'uiautomator2',
"chromeOptions": {'w3c': False},
"chromedriverExecutable": r"C:\Users\Administrator\Desktop\chromedriver_win32\chromedriver.exe"
}
driver = webdriver.Remote("http://127.0.0.1:4723/wd/hub", desired_caps)
driver.implicitly_wait(30)
# 点击活动入口
driver.find_element(AppiumBy.ID, "com.xkw.client:id/iv_horizontal_pic").click()
time.sleep(5)
# 获取contexts
context = driver.contexts
# 切换到webview
driver.switch_to.context(context[-1])
driver.find_element(AppiumBy.ID, "getgifts").click()
time.sleep(1)
# 切换到Native
driver.switch_to.context("NATIVE_APP")
driver.find_element(AppiumBy.ID, "com.xkw.client:id/common_toolbar_back_img").click()
APP中H5调试
- 打开USB调试,连接PC
- 手机或模拟器进入H5页面
- Edge浏览器输入:
edge://inspect/#devices
若使用chrome,则需要代理,否则inspect报404:chrome://inspect/#devices
驱动配置及下载
desired_capabilities需要配置driver目录
'chromedriverExecutableDir': 'browser_driver', # 浏览器版本对应的driver驱动版本存放目录
查看当前手机浏览器版本
Edge浏览器输入:edge://inspect/#devices
对应手机浏览器版本的driver下载
设备操作
等待activity出现操作
driver.wait_activity(activity, timeout, interval=1)
等待目标页面出现,若在设置时间内目标页面出现则直接跳出等待,同时返回True; 若超过设置时间目标页面仍未出现则返回False
- activity:目标activity
- timeout:超时时间设置,单位为s
- interval:循环查询的时间间隔,单位为s,默认为1s
应用场景
主要用于一些应用启动时界面的activity与进入应用时界面的activity不一致,这样就会存在等待时间,而这个等待时间每次可能不一样,故可通过设置超时来等待。
案例
driver = webdriver.Remote("http://localhost:4723/wd/hub", desired_caps)
is_target_activity = driver.wait_activity("com.kugou.common.useraccount.app.KgUserLoginAndRegActivity", 10)
if is_target_activity is True:
print("成功进入目标主页面,可继续执行其他操作")
else:
print("超过未进入目标主页面")
关闭APP和退出设备
driver.close_app() # 关闭当前app
driver.quit() # 关闭驱动连接
android按键操作
常用按键的keycode
KEYCODE_HOME(home键):3
KEYCODE_BACK(back键):4
KEYCODE_SEARCH(搜索键):84
KEYCODE_ENTER(回车键):66
KEYCODE_MENU(菜单键):82
KEYCODE_POWER(电源键):26
KEYCODE_NOTIFICATION(通知键):83
KEYCODE_CALL(拨号键):5
KEYCODE_ENDCALL(挂机键):6
...
点击按键
driver.press_keycode(keycode, metastate=None, flags=None)
driver.keyevent(keycode, metastate=None)
driver.press_keycode(3) # 点击home键
长按按键
driver.long_press_keycode(self, keycode, metastate=None, flags=None)
driver.long_press_keycode(3) # 长按home键
模拟手势点击坐标点操作
tap函数方法介绍
driver.tap(positions, duration=None)
模拟手指(最多支持5个手指)点击某个特定位置并保持一定时间
- positions:坐标位置,列表list类型,每个对象是元组tuple类型(x, y)。
- positions长度,最小为1,最大为5,即格式可为: [(x1, y1), (x2, y2), (x3, y3), (x4, y4), (x5, y5)]。
- duration:持续时间,单位ms,默认为None。
- duration=None表示仅执行点击动作;duration!=None表示执行长按点击动作,维持duration时间后再释放;
获取元素坐标方法
- 通过元素的bounds值来获取点击坐标:
元素的bounds值格式为 [x1, y1][x2, y2],x1和y1为元素的左上角位置,x2和y2为元素的右下角位置。但赋值给positions参数,需要将格式更改一下,改为 [(x1, y1), (x2, y2)]
- 手动获取元素坐标
机器进入“开发者选项”,开启“指针位置”,手动点击元素从而获取元素的坐标
案例
# 长按点击元素坐标,同时保持500ms再释放
driver.tap( [(204, 358), (790, 496)], 500)
driver.press_keycode(4)
driver.tap([(204, 358)], 500)
driver.press_keycode(4)
# 点击元素坐标
driver.tap([(204, 358), (790, 496)])
driver.press_keycode(4)
driver.tap([(204, 358)])
滑动操作
swipe和flick函数方法介绍
driver.swipe(start_x, start_y, end_x, end_y, duration=None)
将屏幕从一个点滑动到另一个点
- start_x:滑动起始点的x轴坐标
- start_y:滑动起始点的y轴坐标
- end_x:滑动结束点的x轴坐标
- end_y:滑动结束点的y轴坐标
- duration:滑动的持续时间,单位ms
driver.flick(start_x, start_y, end_x, end_y)
将屏幕从一个点快速滑动到另一个点
swipe封装
def swipe_left(self):
"""向左滑动屏幕"""
size = self.get_screen_size()
x1 = int(size[0] * 0.95)
x2 = int(size[0] * 0.25)
y = int(size[1] * 0.5)
self.driver.swipe(x1, y, x2, y, 1000) # 滑动持续时间1秒
def swipe_right(self):
"""向右滑动屏幕"""
size = self.get_screen_size()
x1 = int(size[0] * 0.25)
x2 = int(size[0] * 0.95)
y = int(size[1] * 0.5)
self.driver.swipe(x1, y, x2, y, 1000) # 滑动持续时间1秒
def swipe_up(self):
"""向上滑动屏幕"""
size = self.get_screen_size()
x = int(size[1] * 0.5)
y1 = int(size[0] * 0.95)
y2 = int(size[0] * 0.25)
self.driver.swipe(x, y1, x, y2, 1000) # 滑动持续时间1秒
def swipe_down(self):
"""向下滑动屏幕"""
size = self.get_screen_size()
x = int(size[1] * 0.5)
y1 = int(size[0] * 0.25)
y2 = int(size[0] * 0.95)
self.driver.swipe(x, y1, x, y2, 1000) # 滑动持续时间1秒
app操作
app的安装、卸载、判断
-
安装app
driver.install_app(app_path, **options)
- app_path:安装app的路径;
- **options:安装app的其他设置参数,如replace、timeout、allowTestPackages、useSdcard、grantPermissions参数;
- replace:若app已存在于测试机中,是否重新安装,默认为True;
- timeout:等待安装完成的时间,默认为60000ms;
- allowTestPackages:是否允许将安装包标记为测试,默认为False;
- useSdcard:是否使用SD卡安装app,默认为False;
- grantPermissions:安装完成后是否自动授予Android6+上的应用权限,默认为False;
-
判断app是否已安装
driver.is_app_installed(bundle_id)
- bundle_id:要查询的应用程序的ID信息,可用package来判断
-
卸载app
driver.remove_app(app_id, **options)
- app_id:要卸载的应用程序的ID信息
- **options:卸载app的其他设置参数,如keepData、timeout参数;
- keepData:卸载app后是否保留应用程序数据和缓存,默认为False;
- timeout:等待卸载完成的时间,默认为20000ms;
app后台运行、启动、重置、关闭、终止操作
- 启动desired capabilities参数中的应用
driver.launch_app()
- 关闭desired capabilitied参数中运行的应用程序
driver.close_app()
- 将设备当前的应用程序置于后台运行,保持seconds秒后再重新回到前台运行
driver.background_app(seconds)
- seconds:后台运行的时间,单位s
- 重置设备当前的应用程序,将程序恢复到默认
driver.reset()
- 如果某个应用程序app_id正在运行,则终止该应用程序
driver.terminate_app(app_id, **options)
- app_id:要终止的应用程序的ID信息
- **options:要终止的应用程序的其他设置参数,如keepData、timeout参数;
- timeout:等待时间默认为500ms
- 启动某个app
driver.start_activity(app_package, app_activity, **opts)
- app_package:启动应用的包名
- app_activity:启动的activity
- **opts:其他可能需要添加的参数,如app_wait_package、app_wait_activity、intent_action......
- app_wait_package:等待某个应用的包名出现
- app_wait_activity:等待某个应用的界面出现
截图操作
driver.get_screenshot_as_file(filename)
- filename:保存截图的路径+截图名称
若filename不是以.png结尾,则也会执行截图操作,但会有警告提示,故建议一般使用.png结尾的截图。
若截图成功,则返回True;若出现IOError错误则返回False。
截图封装
def get_screen_shot(self, module):
t = time.strftime("%Y-%m-%d_%H_%M_%S")
image_file = file_path("screenshots", f"{module}_{t}.png")
logging.info(f'【{module}】截图:{image_file}')
try:
self.driver.get_screenshot_as_file(image_file)
except Exception as e:
print(e)
滚动元素操作
driver.scroll(origin_el, destination_el, duration=None)
从origin_el元素滚动到destination_el元素
界面为上下滑动:origin_ele在destination_el元素上面时,则执行向下滚动;origin_ele在destination_el元素下面时,则原始元素会滚动到目标元素位置。
界面为左右滑动:origin_ele在destination_el元素左边时,则先执行向右滚动再执行向左滚动;origin_ele在destination_el元素右边时,则先执行向左滚动再执行向右滚动。
注:需要这两个元素在当前界面上存在,否则会报错。
拖拽元素操作
driver.drag_and_drop(origin_el, destination_el)
将origin_el元素拖拽到destination_el元素位置
注:&&需要元素支持拖拽操作&&,比如,桌面icon的拖拽操作
ele1 = driver.find_element_by_xpath("//*[@content-desc='天气']")
ele2 = driver.find_element_by_xpath("//*[@content-desc='安全中心']")
driver.drag_and_drop(ele1, ele2)
打开通知栏操作
driver.open_notifications()
获取连接设备的sessions
curl http://127.0.0.1:4723/wd/hub/sessions | awk -F\"'{PRINT $8}'
使用sessions模拟请求appium
curl -H "Content-Type:application/json;charset=UTF-8\ http://127.0.0.1:4723/wd/hub/session/${sessions}/elements\--data-binary '{"using":"xpath","value"://*}'
adb获取设备uiautomator
adb shell uiautomator dump
ADB操作设备adb shell input
adb输入数据
adb shell input text 123
adb滑动页面
adb shell input swipe 200 500 200 800
进群交流、获取更多干货, 请关注微信公众号:
> > > 咨询交流、进群,请加微信,备注来意:sanshu1318 (←点击获取二维码)
> > > 学习路线+测试实用干货精选汇总:
https://www.cnblogs.com/upstudy/p/15859768.html
> > > 【自动化测试实战】python+requests+Pytest+Excel+Allure,测试都在学的热门技术:
https://www.cnblogs.com/upstudy/p/15921045.html
> > > 【热门测试技术,建议收藏备用】项目实战、简历、笔试题、面试题、职业规划:
https://www.cnblogs.com/upstudy/p/15901367.html
> > > 声明:如有侵权,请联系删除。
============================= 升职加薪 ==========================
更多干货,正在挤时间不断更新中,敬请关注+期待。