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: 防止清空缓存信息
开始录制
复制用例
对复制的用例进行简单改造:
selenium 版本建议 3.141.0
appium-python-client 版本建议 1.2.0
字典caps
功能:配置 Appium 会话,告诉 Appium 服务器需要自动化的平台的应用程序
形式:键值对的集合,键对应设置的名称,值对应设置的值
主要分为三部分:
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
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语法
安卓的工作引擎,速度快,但不支持安卓8以上的版本
官网地址
# ID 定位
driver.find_element_by_android_uiautomator('new UiSelector().resourceId("")' )
# 组合定位
driver.find_element_by_android_uiautomator('new UiSelector().resourceId("com.xueqiu.android:id/tab_name").text("我的")')
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本身是个系统级别的控件,它归属于系统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"
避免页面未渲染完成后操作,导致的报错
示例: 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 里面的一致
获取元素文本element.text
获取元素坐标element.location结果:{‘y’: 19,'x: 498}
获取元素尺寸(高和宽)element.size结果:{‘width’:500,‘height’:22)