APP自动化测试-Appium编写脚本并执行
App自动化测试(学习笔记二)——编写脚本并执行
- Appium Inspctor 功能
- Appium Inspctor 用法
- 用例录制
- capability 配置参数
- app 自动化控制
- 控件定位
- xpath 定位
- UI Automator 原生定位
- css 定位
- 特殊控件 toast 识别
- 强制等待与隐式等待
- 控件交互
Appium Inspctor 功能
- UI分析,元素定位
- 录制用例 **
- 元素查找测试
- Attcah 已有的session
- 云测试
Appium Inspctor 用法
SelectElements:选中元素,查看层级和属性
Swipe By Coordinates:通过坐标点滑动
Tap By Coordinates:通过坐标点点击
Back:返回
Refresh Source & Screenshot:刷新页面
StartRecording:开始录制脚本
Search for element:搜索元素
Copy XML Source to Clipboard:复制 xml 结构
Quit Session & Close Inspector:退出当前 Session
用例录制
获取app的信息
两种方式获取:
通过 logcat 日志获取
mac/Linux: adb logcat ActivityManager:I | grep “cmp"
windows: adb logcat ActivityManager:I | findstr “cmp” 后启动目标应用
通过 aapt 获取
mac/Linux: aapt dump badging wework.apk | grep launchable-activity
Windows: aapt dump badging wework.apk | findstr launchable-activity
启动应用命令
adb shell am start -W -n package-name/activity-name -S
获取当前页面的名字
adb shell dumpsys window w | findstr mCurrent配置待测应用
platformName:平台,Android/iOS
deviceName:设备名
appPackage:应用的包名
appActivity:应用的页面名 Activity
noReset: 防止清空缓存信息开始录制
复制用例
对复制的用例进行简单改造:
- 添加 capability 信息
- 初始化webdriver,添加setup和teardown
- 添加隐式等待和noReset属性增强用例稳定性
- 添加断言
selenium 版本建议 3.141.0
appium-python-client 版本建议 1.2.0
capability 配置参数
字典caps
功能:配置 Appium 会话,告诉 Appium 服务器需要自动化的平台的应用程序
形式:键值对的集合,键对应设置的名称,值对应设置的值
主要分为三部分:
- 公共部分
- ios 部分
- android 部分
Appium 的客户端和服务端之间进行通信的前提
通过 Desired Capabilities 建立会话
公共部分参数配置
键 | 描述 | 值 |
---|---|---|
platformName | 使用的手机操作系统 | iOS,Android,或者 Firefox0S |
platformVersion | 手机操作系统的版本 | 例如 7.1, 4.4 |
deviceName | 使用的手机或模拟器类型 | iPhone Simulator, iPad Simulator, iPhone Retina 4-inch, Android Emulator, Galaxy S4, 等等…. 在 iOS 上,使用 Instruments的 instruments -s devices 命令可返回一个有效的设备的列表。在 Andorid 上虽然这个参数目前已被忽略,但仍然需要添加上该参数 |
automationName | 使用哪个自动化引擎 | android默认使用uiautomator2,ios默认使用XCUTest |
noReset | 在当前 session 下不会重置应用的状态。默认值为 false | true, false |
udid | 连接的真实设备的唯一设备编号 (Unique device identifier) | 例如 1ae203187fc012g |
Android 部分特有参数配置
键 | 描述 | 值 |
---|---|---|
appActivity | Activity 的名字是指从你的包中所要启动的 Android acticity。他通常需要再前面添加. (例如 使用 .MainActivity 代替 MainActivity) | MainActivity, .Settings |
appPackage | 运行的 Android 应用的包名 | com.example.android.myApp, com.android.settings |
appWaitActivity | 用于等待启动的 Android Activity 名称 | SplashActivity |
unicodeKeyboard | 启用 Unicode 输入,默认为 false | true or false |
resetKeyboard | true or false | |
dontStopAppOnReset | 首次启动的时候,不停止 app | true or false |
skipDeviceInitialization | 跳过安装,权限设置等操作 | true or false |
iOS 独有
键 | 描述 | 值 |
---|---|---|
bundleId | 被测应用的 bundle ID 。用于在真实设备中启动测试,也用于使用其他需要 bundle ID 的关键字启动测试。在使用 bundle ID 在真实设备上执行测试时,你可以不提供 app 关键字,但你必须提供 udid 。 | 例如 io.appium.TestApp |
autoAcceptAlerts | 当 iOS 的个人信息访问警告 (如 位置、联系人、图片) 出现时,自动选择接受( Accept )。默认值 false | true 或者 false |
showIOSLog | 是否在 appium 日志中显示从设备捕获的任何日志。默认 | false true or false |
配置优化:添加参数,提高用例的稳定性
{
“noReset”: “true”, // 不清空缓存信息
“dontStopAppOnReset”: “true”, // 首次启动的时候,不停止app
“skipDeviceInitialization”: “true”, // 跳过安装,权限设置等操作
“unicodeKeyBoard”: “true” // 输入中文
}
全部capbility
app 自动化控制
- 启动
启动应用
方式一:webdriver.remote(“url”,desirecapability)
self.driver = webdriver.Remote(“http://127.0.0.1:4723/wd/hub”, desire_cap)
方式二:launch_app() 将应用启动起来
self.driver.launch_app()#手动关闭应用之后,再启动应用(热启动),会进入app首页 - 数据清理
清空输入框内容clear(),每次输入之前都要进行清空
self.driver.find_element(AppiumBy.ID,“io.appium.android.apis:id/text”).clear() - 关闭
退出app回收session,quit()
self.driver.quit()
控件定位
android基础知识:通过容器的布局属性来管理子控件的位置关系,布局过程就是把界面上的所有的控件,根据他们的间距的大小,摆放到正确的位置。
安卓七大布局:LinearLayout(线性布局)、TableLayout(表格布局)、RelativeLayout(相对布局)、FrameLayout(层布局)、AbsoluteLayout(绝对布局)、GridLayout(网格布局)、ConstraintLayout(约束布局)
安卓四大组件:activity页面,与用户交互的可视化界面、service实现程序后台运行的解决方案、content provider内容提供者,提供程序所需要的数据、broadcast receiver广播接收器,监听外部事件的到来,比如来电
常用控件:TextView文本框控件、EditText可编辑文件控件、Button、ImageButton图片按钮、ToggleButton开关按钮、ImageView 显示图片的控件、CheckBox复选框控件、RadioButton单选框控件
布局是一种可用于放置很多控件的容器,它可以按照一定的规则调整内部控件的位置,从而编写出精美的界面。当然,布局的内部除了放置控件外,也可以放置布局,通过多层布局的嵌套,我们就能够完成一些比较复杂的界面。
————————
ios 基础知识:苹果操作系统,给iPhone,iTouch,iPad使用,目前是ios13.ios去掉了布局的概念,直接用变量之间的相对关系完成位置的计算。系统:MacOSX 开发工具:Xcode 开发语言:ObjectC 安装文件:.ipa文件、.app文件
使用Appium测试ios应用需要使用MacOS操作系统
————————
控件基础知识:
dom:Document Object Model 文件对象模型。
dom应用:最早用于html和js交互。用于表示界面的控件层级,界面的结构化描述,常见的格式为html、xml。核心元素为节点和属性。
xpath:xml路径语言,用于xml中的节点定位。
android应用的层级结构与html不一样,是一个定制的xml
app source 类似于dom,表示app的层级,代表了界面里面所有的控件树的结构。
每个控件都有它的属性(id 、 aid 、 xpath),没有css属性
每个节点node,含各种属性attribute:clickable、text、resource-id、content-desc、bounds
(ios与android的区别:dom属性节点结构类似,名字和属性命名不同)
————————
定位工具
ui automator viewer定位工具(ONLY Android)
安装:Android SDK 自带的界面分析工具,打开 tools/bin 目录下的 uiautomatorviewer 程序
左上角4个按钮的功能:
第一个按钮是通过分析给定的文件定位
第二个按钮是将当前界面截图并分析xml结构(用的最多~)
第三个按钮与第二个功能类似,可快速加载,但它会对页面内容进行压缩,导致一些控件定位不准确
第四个按钮是保存当前界面的截图以及xml结构weditor
要求:python 3.6+ 以上
安装:weditor 是 python 的第三方库,支持 Android 和 iOS 的界面分析,pip install weditor 进行安装
运行:安装完成之后,在命令行运行 python -m weditor 即可
直接启动了一个服务,通过设备的 uuid 连接设备,展示页面结构。appium inspector(***)
github appium-inspector
运行 appium inspector、运行 appium server、本地的 adb 已连接设备、Desired Capabilities 参数填写
点击 Start Session
注意:在运行appium inspect 的时候需要检查一下weditor在手机上安装的ATX服务是否停止,因为ATX服务会占用uiautomator2的
xpath 定位
XPath语法
UI Automator 原生定位
安卓的工作引擎,速度快,但不支持安卓8以上的版本
官网地址
# ID 定位
driver.find_element_by_android_uiautomator('new UiSelector().resourceId("<element-ID>")')# 组合定位
driver.find_element_by_android_uiautomator('new UiSelector().resourceId("com.xueqiu.android:id/tab_name").text("我的")')
css 定位
Android: Appium Server 版本 >= 1.19.0
iOS:Appium Server>= 1.21.0
css selector 会转化为 Android/iOS 原生定位的定位策略
Android 转为 Android Uiautomator 定位方式
iOS 转为 class chain 定位方式
driver.find_element(AppiumBy.CSS_SELECTOR,"#com\.xueqiu\.android\:id\/tv_search")
Appium Server 解析前:
{"using":"css selector","value":"#com\\.xueqiu\\.android\\:id\\/tv_search"}
Appium Server 解析后:
{"strategy":"-android uiautomator","selector":"new UiSelector().resourceId(\"com.xueqiu.android:id/tv_search\")",...}
cssselector用法官方说明
# 通过 id
elementById("someResourceID")`-> `elementsByCss("#someResourceID")
# 通过 class
elementsByClassName("android.widget.TextView")`-> `elementsByCss("android.widget.TextView")
# 通过 accessibility id
elementsByAccessibilityId("Some Content Description")`-> `elementsByCss('*[description="Some Content Description"]')
# 通过 xpath
elementsByXpath("//android.widget.TextView[@description='Accessibility']")`-> `elementsByCss("android.widget.TextView[description='Accessibility']")
特殊控件 toast 识别
一闪而过的消息提示
toast本身是个系统级别的控件,它归属于系统settings,当一个app发送消息的时候,不是自己造出来的弹框,是发给系统,由系统统一进行弹框,这类的控件不在app内,需要特殊的控件识别办法。
必须使用xpath查找
self.driver.find_element(AppiumBy.XPATH, "//*[@class='android.widget.Toast']")
self.driver.find_element(AppiumBy.XPATH, "//*[contains(@text,'xxxxx')]")
caps["automationName"] = "uiautomator2"
强制等待与隐式等待
避免页面未渲染完成后操作,导致的报错
- 强制(直接)等待
解决方案:在报错的元素操作之前添加等待
原理:强制等待,线程休眠一定时间
time.sleep(3) - 隐式等待
问题:难以确定元素加载的具体等待时间。
解决方案:针对于寻找元素的这个动作,使用隐式等待添加配置。
原理:隐式等待是一种全局的等待方式,设置一个等待时间,轮询查找(默认 0.5 秒)元素是否出现,如果没出现就抛出异常
driver.implicitly_wait(3) - 显式等待
隐式等待无法解决的问题
元素可以找到,使用点击等操作,出现报错
原因:
页面元素加载是异步加载过程,通常 xml 会先加载完成,相应的元素属性后加载
元素存在与否是由 xml 决定,元素的交互是由属性决定
隐式等待只关注元素能不能找到,不关注元素能否点击或者进行其他的交互
示例: WebDriverWait(driver实例, 最长等待时间, 轮询时间).until(结束条件)
原理:在最长等待时间内,轮询,是否满足结束条件
WebDriverWait(driver, 10).until(expected_conditions.element_to_be_clickable((AppiumBy.ID, ‘com.xueqiu.android:id/code’)))
driver.find_element(AppiumBy.ID,“com.xueqiu.android:id/code”).click()
locator = (AppiumBy.XPATH, "//*[@text='SH601601']/../../..//*[@resource-id='com.xueqiu.android:id/current_price']")
WebDriverWait(self.driver,10).until(expected_conditions.visibility_of_element_located(locator))
price = self.driver.find_element(*locator).text
print(f"股票的价格是{price}")
# price_ele = WebDriverWait(self.driver,10).until(lambda x:x.find_element(*locator))
# print(f"股票的价格是{price_ele.text}")
总结
类型 | 使用方式 | 原理 | 适用场景 |
---|---|---|---|
直接等待 | time.sleep(等待时间)) | 强制线程等待 | 调试代码,临时性添加 |
隐式等待 | driver.implicitly_wait(等待时间) | 在时间范围内,轮询查找元素 | 解决找不到元素问题,无法解决交互问题 |
显式等待 | WebDriverWait(driver实例, 最长等待时间, 轮询时间).until(结束条件) | 设定特定的等待条件,轮询操作 | 解决特定条件下的等待问题,比如点击等交互性行为 |
控件交互
元素的常用方法
点击方法 element.click()
输入操作 element.send_keys(‘appium’)
设置元素的值 element.set_value(‘appium’)
清除操作 element.clear()
是否可见 element.is_displayed() 返回 True/False
是否可用 element.is_enabled() 返回 True/False
是否被选中 element.is_selected() 返回 True/False
获取属性值 get_attribute(name)
get_attribute() 方法能获取的属性,元素的属性几乎都能获取到,属性名称和 uiautomatorviewer 里面的一致
- resource-id/resourceld 返回 resource-id(API=>18 支持)
- text 返回 text
- class 返回 class(API=>18 支持)
- content-desc/contentDescription 返回 content-desc 属性
- checkable,checked,clickable,enabled,focusable,focused,{long-clickable,longClickable), package, password,scrollable,selection-start,selection-end,selected,bounds,displayed,contentSize 返回 true or false
获取元素文本element.text
获取元素坐标element.location结果:{‘y’: 19,'x: 498}
获取元素尺寸(高和宽)element.size结果:{‘width’:500,‘height’:22)
APP自动化测试-Appium编写脚本并执行相关推荐
- app自动化测试appium教程之番外1——进阶补充内容
app自动化测试appium教程之番外1--进阶补充内容 混合app测试 1. 打开app内webview debug模式 2. 验证是否为混合app 3. 切换至H5页面 4. 切回原生app 5. ...
- APP自动化测试——Appium运行环境搭建保姆级教程
APP自动化测试运行环境比较复杂,稍微不注意安装就会失败.我见过不少朋友,装了1个星期,Appium 的运行环境还没有搭好的. 搭建环境本身不是一个有难度的工作,但是 Appium 安装过程中确实存在 ...
- app自动化测试appium教程之二——adb命令
adb命令 ADB简介 获取包名和界面名 文件传输 获取app启动时间 获取手机日志[应用] 其他adb命令 教学视频参考b站课程,此文为学习记录 (免费的羊毛,要薅呀,筒子们~) 零基础入门移动自动 ...
- app自动化测试appium教程之三——appium基础命令(python)
app自动化测试教程之三--appium基础命令(python) hello appium 基础操作API 教学视频参考b站课程,此文为学习记录 (免费的羊毛,要薅呀,筒子们~) 零基础入门移动自动化 ...
- App自动化测试 —— Appium的使用
目录 简介 安装 配置 & Run 问题 & 解决方案 优点 & 缺点 总结 简介 Appium是一个开源测试自动化框架,用于原生. 混合和移动 Web 应用程序. 安装 Ap ...
- APP自动化测试-Appium日志分析
下面是我们的代码脚本:(环境准备工作就不在这里讲述,自行百度) 下图中,appium作为server端收到客户端发出的post请求,可以看到请求参数就是我们代码里面写的那些字段信息 appium收到请 ...
- 集成——Mac电脑上app自动化测试(Appium + xcode 8.2 + python)环境搭建
1.Mac电脑.xcode.appium客户端1.6.4,appium1.6.4, android studio 命令行安装: 2.安装brew /usr/bin/ruby -e "$(cu ...
- linux shell编写脚本,执行命令同时操作多台主机
执行命令同时查看多台主机jps #!/bin/bashparams=$@ i=201 for (( i = 1 ; i <= 3 ; i = $i + 1 )) ; doecho ======= ...
- 关于APP自动化测试框架
介绍几个APP自动化框架 当前比较流行和出名的APP自动化框架分别为 appium.uiautomator2.poco和airtest(后面两个都是网易团队开源,并且有独立IDE支持) appium ...
- selenium编写脚本_Selenium脚本编写技巧和窍门
selenium编写脚本 如果您刚刚开始学习Selenium,则以下技巧和窍门将成为您的救星. 这些技巧和窍门具有您可能会忘记的所有基本知识,将帮助您记住所有这些. 您只需浏览一次,几秒钟后您便会了解 ...
最新文章
- SSM框架整合(Spring+SpringMVC+MyBatis)
- gdb常用调试命令汇总!
- ios架构篇-2 国际化多语言
- Linux: debian/ubuntu下安装和使用Java 8
- redis sorted_set数据类型常用命令及跳表skip_list原理
- SAP CRM 中间件里的发布-订阅者模式
- int 范围_Java学习之随机生成5个(范围1——33)不同数字的思考
- matplotlib散点图笔记
- JAVA GC(Garbage Collection)及OOM那些事
- opencv库skimage 实现Canny边缘探测算法
- linux buffer 刷到磁盘,Linux下的磁盘缓存 linux page buffer cache深入理解
- trunk端口_超全!华为交换机端口vlan详解~
- python自建模块_python导入自建模块的问题
- 计算机office demo,办公软件应用(Office2007)中级_DEMO盘-2013
- oracle sqlldr decode,sqlldr时遇到的一个问题
- 使用阿里云短信API接口
- 12306自动抢票软件
- IT民工,你的未来在哪里?
- AliOS Things的SDK ESP8266 连接阿里生活物联网平台 配网失败解决方案
- HAL库-us级延时函数实现
热门文章
- 解决swift实现的websocket与后台通信问题:websocket is disconnected: masked and rev data is not currently supported
- 成为快乐高产的程序员的小诀窍。
- IntelliJ IDEA中文汉化教程
- 数据库设计5-逻辑结构设计
- 【IoT】产品设计:OEM、ODM、EMS 的区别是什么?
- 两个自然数互素(relatively prime)
- redis突然宕机数据会丢失吗
- Vuex5.0?大菠萝Pinia挺好的~
- 桌面版 Linux 为什么打不过 Windows?Linus 现身说法!
- HTML+CSS三栏式布局(7种)