文章目录
前言
阅读本文前请注意最后编辑时间,文章内容可能与目前最新的技术发展情况相去甚远。欢迎各位评论与私信,指出错误或是进行交流等。
adb调试工具
ADB 全称为 Android Debug Bridge,起到调试桥的作用,是一个客户端-服务器端程序。其中客户端是用来操作的电脑,服务端是 Android 设备
ADB 也是 Android SDK 中的一个工具,可以直接操作管理 Android 模拟器或者真实的 Android 设备。
adb组成
adb包含三个部分:
1.Client端:运行在开发机器中,即你的开发电脑,用来发送adb命令;
2.Daemon守护进程:运行在调试设备中,手机或模拟器,用来接收并执行adb命令;
3.Server端:同样运行在开发机器中,用来管理Client端和手机的Daemon之间的通信。
1.client端将命令发送给server端
2.server端会将命令发送给daemon端
3.daemon端进行执行
4.将执行结果,返回给server端
5.server端将结果再返回给client端
常用命令
获取程序的包名和界面名
1.包名(package):决定程序的唯一性(不是应用的名字)
2.界面名(activity):可以理解为,一个界面名,对应着一个界面。
应用场景:
自动化测试需要通过代码的形式告诉手机测试哪个应用程序的哪一个界面,所以需要通过这个命令进行获取。
使用步骤
1.打开需要测试的应用程序
2.在电脑的终端输入adb命令(电脑已经与移动设备连接)
# Mac/Linux:
adb shell dumpsys window windows | grep mFocusedApp
# Windows:
adb shell dumpsys window windows | findstr mFocusedApp
上图中 打开了手机的设置,包名:com.android.settings 界面名:.Settings
文件传输
发送文件到手机
应用场景
将手机需要的数据、文件 在电脑上调整好,直接发送给手机
命令格式
adb push 电脑的文件路径 手机的文件夹路径
# 示例 将桌面的a.txt发送到手机的sd卡
adb push c:\users\hm\besktop\a.txt /sdcard
从手机中拉取文件
应用场景
将手机产生的文件(数据库文件,日志文件)拉取到电脑中
命令格式
adb pull 手机的文件路径 电脑的文件夹路径
# 示例 将手机的sd卡的a.txt拉取到桌面
adb pull /sdcard/a.txt C:\users\hm\besktop
获取app启动时间
应用场景
1.如果企业对应用程序的启动速度有要求,则需要使用这个命令进行测试
2.测试标准:参照同类软件,启动时间不能超出一倍即可
命令格式
adb shell am start -w 包名/启动界面名
# 示例 启动 com.android.settings程序并且进入主界面(.Settings)
adb shell am start -w com.android.settings/.Settings
获取手机日志
应用场景
将bug的日志信息发送给开发人员,便于开发人员定位bug
使用步骤
1.打开需要测试的应用程序
2.找到触发bug的位置
3.使用查看日志命令
4.触发bug
5.获取日志信息
命令格式
adb logcat
其他命令
adb install 路径/xx.apk # 安装app 到手机
adb uninstall 包名 # 卸载手机上的app,需要指定包名
adb devices # 获取当前电脑已经连接设备和对应的设备号
adb shell # 进入到安卓手机内部的linux系统命令行中
adb start-server # 启动adb服务端,出bug时使用可以重启服务器,先关闭再启动
adb kill-server # 停止adb服务端,出bug时使用可以重启服务器,先关闭再启动
adb --help # 查看adb帮助,命令记不清楚时有用
Appium 简介
Appium 是一个移动 App 自动化框架。
能够完成的任务:
- 自动化完成一些重复性的任务
- 比如微信客服机器人
- 爬虫
- 自动化测试
Appium 自动化方案的特点:
- 开源免费
- 支持多个平台
Appium支持Android和iOS平台的自动化测试,使用相同的API可以编写跨平台的测试脚本。 - 支持多种类型的自动化
无论是原生移动应用(APP)、混合应用(Hybrid App)和移动网页应用(H5),Appium都支持自动化测试。 - 支持多种编程语言
- 使用标准的WebDriver协议
Appium使用WebDriver协议来与移动设备进行通信,这使得开发人员可以使用熟悉的API和命令,无需学习新的测试框架。
工作原理图
包含了 3个主体部分 : 自动化程序、Appium Server、移动设备
自动化程序
自动化程序是程序员开发的,实现具体的 手机自动化 功能。
要发出具体的指令控制手机,需要使用 客户端库。
和Selenium一样,Appium 组织 也提供了多种编程语言的客户端库,包括 java,python,js, ruby等,方便不同编程语言的开发者使用。
我们需要安装好客户端库,调用这些库,就可以发出自动化指令给手机。Appium Server
Appium Server 是 Appium 组织开发的程序,它负责管理手机自动化环境,并且转发 自动化程序的控制指令 给 手机,并且转发 手机给 自动化程序的响应消息。设备
这里说的设备,不仅仅是手机,包括所有 苹果、安卓的移动设备,比如:手机、平板、智能手表等。
为了直观方便的讲解,这里我们简称: 手机
设备为什么能 接收并且处理自动化指令呢?
因为,Appium Server 会在手机上 安装一个 自动化代理程序, 代理程序会接收自动化指令,并且执行自动化指令
比如:要模拟用户点击界面按钮,Appium 自动化系统的流程是这样的:
1.自动化程序 调用客户端库相应的函数, 发送 点击元素 的指令(封装在HTTP消息里)给 Appium Server
2.Appium Server 再转发这个指令给 手机上的自动化代理
3.手机上的自动化代理 接收到 指令后,调用手机平台的自动化库,执行点击操作。返回点击成功的结果给 Appium Server
Appium Server 转发给 自动化程序
4.自动化程序了解到本操作成功后,继续后面的自动化流程
自动化代理控制,使用的什么库来实现自动化的呢?
如果测试的是苹果手机, 用的是苹果的 XCUITest 框架 (IOS9.3版本以后)
如果测试的是安卓手机,用的是安卓的 UIAutomator 框架 (Android4.2以后)
这些自动化框架提供了在手机设备上运行的库,可以让程序调用这些库,像人一样自动化操控设备和APP,比如:点击、滑动,模拟各种按键消息等。
环境搭建
安装客户端库(appium lib)
根据原理图, 我们知道自动化程序需要调用客户端库和 Appium Server 进行通信。
因为我们介绍Python语言的客户端库,使用以下命令进行安装。
pip install appium-python-client
手动下载方式:
appium lib,下载地址:http://appium.io/downloads.html
选择Python版本的Lib 例如 Appium-Python-Client-0.22.tar.gz
其他依赖(自行下载并安装)
python, 下载地址:https://www.python.org/
Appium依赖于Selemium,所以还要下载 Selemium Lib: selenium-2.53.2.tar.gz https://pypi.python.org/pypi/selenium
安装Appium Server
下载地址:http://appium.io/
根据自己的OS进行安装程序的选择
直接打开下载完成的安装程序,一直下一步即可。
其他依赖(自行下载并安装)
nodejs,下载地址:https://nodejs.org/en/
安装JDK(自行下载并安装)
要对安卓APP进行自动化测试,必须要安装安卓SDK,而安卓SDK需要 JDK 环境。
安装 Android SDK
对于安卓APP的自动化,Appium Server 需要 Android SDK。
因为要用到里面的一些工具,比如 要执行命令 设置手机、传送文件、安装应用、查看手机界面等。
下载地址:http://developer.android.com/sdk/index.html,下载sdk tools
国内下载地址:http://www.androiddevtools.cn/
下载最新的 Android SDK文件包: androidsdk.zip ,并且解压,即可。
解压完成后,需要 配置一下 添加一个 环境变量 ANDROID_HOME ,设置值为sdk包解压目录,比如 d:\tools\androidsdk
另外,还推荐大家再添加一个 环境变量 ,加入 adb所在目录, d:\tools\androidsdk\platform-tools
如果是通过Android SDK Manage来下载 Android SDK包的话, 可参考
https://austin.blog.csdn.net/article/details/126364649
连接手机
上述的软件环境都准备好以后
启动 appium 服务器
进入 手机设置 -> 关于手机 ,不断点击 版本号 菜单(7次以上),
退出到上级菜单,在开发者模式中,启动USB调试
(注:不同手机这里打开方式不一样,一般手机在【关于手机】里找到【版本号】,连续点击【版本号】7次,即可进入开发者模式。
在你运行程序的电脑上 用 USB线 连接上 你的安卓手机
手机界面弹出 类似 如下提示。
选择 允许USB调试。
注意:
有的手机系统,可能需要一些额外的设置。
比如,有的手机,开发者选项里 需要打开 允许通过USB安装应用 等。
连接好以后,打开CMD命令行窗口, 执行 adb devices 命令来列出连接在电脑上的安卓设备。
输出手机的deivce id
表示电脑上可以查看到 连接的设备,随后就可以运行自动化程序了。
device id 可以在手机的【设置】中的【状态消息】可以查到。
注:如果出现device not found,优先检查手机的驱动是否安装正确,也可以到硬件管理器中去查看对应的设备驱动是否异常。
这里推荐使用adb driver installer这个软件来安装对应的设备驱动,网上很多的,随便百度一下都有下载。
如果像图中显示出现了多个设备连接,其中一个的端口是5555 的话,后续的一些操作可以指定对应的device id去进行操作,比如 adb -s XXXXXX(device id) shell
来进行操作。
运行相关APP
我们想要通过Appium来运行相关APP,还需要获取与APP相关的几个参数。
appPackage:包名,在Android系统中是判断一个App的唯一标识。
appActivity:界面名。
platformName:设备的平台名,Android或iOS。
deviceName:设备名,这里填入刚才ADB里的device id即可。
以下为获取appPackage与appActivity的几种方法。
查看源代码
如果被测对象是自研的APP,直接问下对应开发同学,这两个参数的值就可以使用ADB
在手机连接的状态下,先打开想操作的APP,之后在cmd中输入adb shell "dumpsys window | grep mCurrentFocus"
即可查看对应APP的appPackage了。如果有多个设备,则需要先用adb -s XXXX shell
来制定进入的设备,再输入dumpsys window | grep mCurrentFocus
查看即可。
红框处的就是appPackage。但这里需要注意,因为你进入APP后可能会进行其他操作,所以当前APP所在的页面不一定是启动页面,所以appActivity的值不一定是对的。
使用monkey命令来进行appActivity的获取,使用命令adb shell monkey -p com.xxxxxxx(appPackage) -vvv 1
来进行获取。
连接手机模拟器
关于手机模拟器如何下载安装 请各位自行查阅资料
以学习通为测试对象,打开雷电模拟器,下载学习通。然后启动学习通,登录进入主页面。
启动雷电模拟器
启动Appium
点击右上角的搜索符号,开启Appium Server。
这里需要编辑一个用于连接模拟器并打开学习通的参数配置(Desired Capabilities),具体有四个核心的参数,分别为platformName,deviceName,appPackage,appActivity。
由于雷电模拟器是Android,所以platformName为Android
win+R键打开cmd窗口,输入adb devices
,结果如图所示,所以deviceName即为emulator-5554,也就是雷电模拟器的设备名。
adb shell dumpsys activity | findstr "mResume"
# Android 8.1之下版本使用
adb shell dumpsys activity | findstr "mFocus"
查看学习通应用的appPackage和appActivity(必须保证雷电模拟器的学习通应用程序处于开启状态)如图所示。appPackage为com.chaoxing.mobile,appActivity为.main.ui.MainTabActivity
所以最终配置如下:
这里多设置了一个noReset,这个参数表明不停止应用程序和清除应用程序数据。
点击Start Session,等待一段时间(Appium会驱动雷电模拟器重启学习通,如果学习通处于黑屏状态导致连接失败,退出学习通,重新点击Start Session连接一次应该就可以了)如果出现以下界面,表示连接成功。
Appium基础操作
注意:进行这些操作前 已启动appium server 并 已连接设备/模拟器
通过代码启动应用
from appium import webdriver
desiredcaps = dict()
#启动配置参数
desired_caps['platformName'] = 'Android' # 平台为安卓
desired_caps['platformversion'] = '5.1' # 安卓版本
desiredcaps['deviceName'] = '192.168.56.101:5555' # 设备名 由adb命令获取
#应用参数
desired_caps['apppackage'] = 'com.android.settings' # 某个应用的包名
desired_caps['appActivity'] = '.Settings' # 应用的界面名
#获取driver 地址为appium server的地址
driver = webdriver.Remote('http://localhost:4723/wd/hub',desired_caps)
#退出driver
driver.quit()
应用跳转
应用场景
如果一个应用需要跳转到另外一个应用,就可以使用这个api进行应用的跳转,就像我们通过外卖应用下订单之后会跳转到支付应用一样。
# 脚本内启动其他app
# 参数:
# apppackage:要打开的程序的包名
# appActivity:要打开的程序的界面名
driver.start_activity(apppackage,appActivity)
获取app的包名和界面名
# 获取属性
drive.current_package
drive.current_activity
关闭app和关闭驱动
# 关闭当前操作的app,不会关闭驱动对象
driver.close_app()
#关闭驱动对象,同时关闭所有关联的app
driver.quit()
安装和卸载应用
# 安装app
# app_path:apk路径
driver.install_app(app_path)
# 卸载app
# app_id:应用程序包名
driver.remove_app(app_id)
# 判断app是否已经安装
# app_id:应用程序包名
#返回值:
# 布尔类型,True为安装,False为没有安装
driver.is_app_installed(app_id)
将应用置于后台
应用场景
银行类app会在进入后台一定时间后,再回到前台页面会重新输入密码,如果需要自动化测试这种功能,可以使用这个api进行测试
# app放置到后台一定时间后再回到前台,模拟热启动
# seconds:后台停留多少秒
driver.background_app(seconds)
Appium元素定位
和Selenium Web自动化一样,要操作界面元素,必须先 定位元素。
Appium是基于Selenium的,所以 和 Selenium 代码 定位元素的 基本规则相同:
find_element_by_XXX 方法,返回符合条件的第一个元素,找不到抛出异常
find_elements_by_XXX 方法,返回符合条件的所有元素的列表,找不到返回空列表
通过 WebDriver 对象调用这样的方法,查找范围是整个界面
通过 WebElement 对象调用这样的方法,查找范围是该节点的子节点
界面元素查看工具
做 Selenium Web 自动化的时候,要找到元素,我们是通过浏览器的开发者工具栏来查看元素的特性,根据这些特性(属性和位置),来定位元素
Appium 要自动化手机应用,同样需要工具查看界面元素的特征。
常用的查看工具是: Android Sdk包中的 uiautomateviewer 和 Appium Desktop 中的 Appium Inspector
uiautomateviewer
安卓查看APP界面元素,可以使用 Android SDK 中的工具 uiautomateviewer 。
使用步骤
1.进入SDK目录下的目录
mac在tools/bin 目录下,打开 uiautomatorviewer
windows在tools目录下,打开 uiautomatorviewer.bat
2.电脑连接真机或打开android模拟器
3.启动待测试app
4.点击uiautomatorviewer的左上角Device Screenshot(从左数第二个按钮)
5.uiautomatorviewer上就会同步显示启动的app以及对应的页面,在其内部点击希望查看的控件
6.查看右下角Node Detail相关信息
Appium Inspector
Appium Desktop 中的 Appium Inspector 也可以查看元素。
(在某些版本中,需要去官网单独下载安装Inspector,参考 https://blog.csdn.net/NoamaNelson/article/details/134947987)
点击放大镜图标来开启Appium Server。
启动后界面如下
配置Desired Capabilities
要启动APP就需要填写对应APP的启动参数。
通过右边的加号来进行属性的添加
填入获取的各项参数
填写完成后后边会出现JSON格式的表示信息,然后点击【Start Session】即可启动APP。
启动时,会在测试手机上安装Appiium的APP,启动完成后手机会自动打开你要启动的APP,并且在Inspector上显示与APP同步的画面。
Inspector界面说明
自左向右,依次为:
Native App Mode:切换为原生APP模式;
Web/Hybrid App Mode:切换为混合APP模式,如果APP有内有小程序(Uni App)或者H5的话可以试试这个模式;
Select Elements:选择元素模式,在左侧预览窗口中鼠标的点击模式会变成元素的选取,而不是模拟点击的操作,类似于浏览器开发者工具中的选择元素;
Swipe By Coordinates:使用坐标滑动,顾名思义,就是利用鼠标在A和B点分别进行点击,之后会根据点击的顺序与方向进行相应方向的滑动动作模拟;
Tap By Coordinates:使用坐标点击,类似于现实中的点击动作,用哪点哪,同步设备与预览窗的画面;
Back:退回上一步,类似手机的返回按钮;
Refresh Source & Screenshot:刷新资源与截图,一般在Select Element模式下用的比较多一点,在元素抓取的过程中如果需要查看功能互动或页面跳转的时候可以进行画面的刷新操作,但Swipe By Coordinates与Tap By Coordinates模式下就用不太到了;
Start Recording:开始录制,我们可以在打开这个选项后直接对APP的预览画面进行一些操作,Appium会自动帮我们把动作转换成指定语言的相关代码;
该功能不太推荐测试同学使用,特别是已经有简单代码基础的同学,它默认会使用xpath的定位方式。xpath的定位方式十分的脆弱,特别是绝对路径定位,一旦发生变化,脚本的维护就会变得十分的困难,如果一定要用,推荐使用相对路径的定位方法。
Search for element:搜索元素,我们可以根据各类元素的定位条件进行元素的相关搜索,方便我们快速定位。
Copy XML Source to Clipboard:复制页面元素,可以将该页面中所有的元素信息复制。
Quit Session & Close Inspector:关闭会话且关闭Inspector。
当我们选中一个元素后,被选中的元素会显示以下选项,自左向右依次为:
Tap:模拟点击;
Send Keys:如果为输入框的话可以使用这个选项来填写对应的内容;
Clear:可以对编辑框内的内容进行清除;
Copy Attributes to Clipboard:将选中的元素相关信息复制到粘贴板中;
Get Timing:获取选中的元素响应所需的时长。
定位方法(仅介绍常用方法)
在Inspector获取了APP界面元素的属性之后,结合Python代码根据属性利用合适的定位方法来定位元素。
id定位
安卓应用元素的 id 或 resource-id 属性,一般来说是唯一值,使用Inspector就可以定位到,查到值之后可以使用搜索查看下是否唯一。
# 方法已弃用
driver.find_element_by_id('expand_search')
from appium import webdriver
from base.base_driver import driver_setup
from appium.webdriver.common.appiumby import AppiumBy
driver = webdriver.Remote('http://localhost:4723/wd/hub', driver_setup())
# 方法已弃用
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'))
CLASS NAME
安卓界面元素的 class属性 界面中相同class属性的元素重复几率较高, 通常不是唯一的。
一般根据class 属性来选择元素, 是要选择多个而不是一个。
如果要查找的 界面元素的class属性 在当前界面中只有一个,可以根据class 来唯一选择。
driver.find_elements_by_class_name('android.widget.TextView')
driver.find_element(AppiumBy.CLASS_NAME('android.widget.EditText'))
ACCESSIBILITY ID
元素的 content-desc 属性是用来描述该元素的作用的,类似于备注。
如果要查询的界面元素有 content-desc属性,我们可以通过它来定位选择元素。
driver.find_element_by_accessibility_id('找人')
driver.find_element(AppiumBy.ACCESSIBILITY_ID('这是一个按钮'))
Xpath
Appium 也支持通过 Xpath选择元素。
但是其可靠性和性能不如 Selenium Web自动化。因为Web自动化对Xpath的支持是由浏览器实现的,而Appium Xpath的支持是 Appium Server实现的。
介绍几种常用的xpath定位方法方法。表达式的语法规则和 以前学习的Selenium里面Xpath的语法是一样的
唯一属性定位
如果页面中属性的text或id是固定且唯一的,可以使用以下方法。
# text属性唯一
driver.find_element(AppiumBy.XPATH('//*[@text="顾客名称"]'))
这里的 // 指的是相对路径,* 代表匹配所有,@ 是查找对应的指定属性,这里是通过text来定位的所以就在@后面填写text,之后跟上具体的属性值即可。
# id属性唯一
driver.find_element(AppiumBy.XPATH('//*[@resource-id="com.tiffany.rta.debug:id/edt_customer_name"]'))
# class属性唯一
driver.find_element(AppiumBy.XPATH('//*[@class="android.widget.EditText"]'))
模糊匹配定位
与text中的模糊匹配类似,是在不太清楚具体xpath路径时或具体值可能变动的情况下快速定位匹配的方法。
# 以text属性为例,class、id方法类似
driver.find_element(AppiumBy.XPATH('//*[contains(@text="新增")]'))
组合定位
# id和text属性
driver.find_element(AppiumBy.XPATH('//*[@resource-id="com.tiffany.rta.debug:id/edt_customer_name" and @text="顾客名称"]'))
相对路径搭配属性
driver.find_element_by_xpath('//ele1/ele2[@attr="value"]')
注意:在appium中, xpath表达式中 每个节点名 是元素的class属性值。
安卓 UIAutomator
根据id,classname, accessibilityid,xpath,这些方法选择元素,其实底层都是利用了安卓 uiautomator框架的API功能实现的。
参考 谷歌安卓官方文档介绍:https://developer.android.google.cn/training/testing/ui-automator
也就是说,程序的这些定位请求,被Appium server转发给手机自动化代理程序,就转化为为uiautomator里面相应的定位函数调用。
其实,我们的自动化程序,可以直接告诉 手机上的自动化代理程序,让它 调用UI Automator API的java代码,实现最为直接的自动化控制。
介绍比较常用的Uiautomator的定位方法:
text定位
driver.find_element(AppiumBy.ANDROID_UIAUTOMATOR, 'new UiSelector().text("请输入顾客姓名")')
text模糊定位
定位text较长的元素时,就可以使用模糊匹配的方法textContains来进行元素的定位。
driver.find_element(AppiumBy.ANDROID_UIAUTOMATOR, 'new UiSelector().textContains("姓名")')
text正则匹配定位
driver.find_element(AppiumBy.ANDROID_UIAUTOMATOR, 'new UiSelector().textMatches("^请输入.*")')
resourceId定位
find_element(AppiumBy.ANDROID_UIAUTOMATOR, 'new UiSelector().resourceId("com.tiffany.rta.debug:id/edt_customer_name")')
resourceId正则匹配定位
driver.find_element(AppiumBy.ANDROID_UIAUTOMATOR, 'new UiSelector().resourceIdMatches(".+edt_customer_name")')
className定位
driver.find_element(AppiumBy.ANDROID_UIAUTOMATOR, 'new UiSelector().className("android.widget.EditText")')
className正则匹配定位
driver.find_element(AppiumBy.ANDROID_UIAUTOMATOR, 'new UiSelector().classNameMatches(".*EditText")')
组合定位
# 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("顾客名称")')
查找多个元素
与Selenium雷系,如果同一页面中某一属性有多个元素时,可以使用driver.find_elements的方法定位到多个元素,然后采用下标来指定想要操作的元素。
# 定义输入框,画面中共有3个输入框
element = driver.find_elements(AppiumBy.CLASS_NAME('android.widget.EditText'))
# 指定第一个输入框中输入“张三”
element[0].send_keys("张三")
隐式等待与显示等待
与Selenium同样的,Appium也可以对元素设置隐式等待与显示等待
隐式等待:所有定位元素的超时时间设置为同一个值,等待元素加载指定的时长,超出时长抛出NoSuchElementException异常
显示等待:单独对某元素的设置超时时间,等待元素加载指定的时长,超出时长抛出TimeoutException异常
# 隐式等待
driver.implicitly_wait(5);
# 显示等待
# 1.导包 请注意这里导的是selenium包
# 2.创建WebDriverWait对象
# 3.调用WebDriverWait对象的until方法
from selenium. webdriver . support . wait import webDriverwait
# 创建WebDriverwait对象 在5秒钟内,每间隔1秒进行寻找元素
wait=webDriverwait(driver,5,poll_frequency=1)
#获取元素并设置超时时间和频率
element=wait.until(lambdax:x.findelementby-xpath("//*[contains(@content-desc,'收起')]“))
注意点
- Android与iOS中元素定位的差异点在于,Android的元素如果不在当设备画面中,比如需要上划或者下划才(swipe)能看见的元素,需要先做对应操作让其展示出后才能进行元素的定位。而iOS则完全不需要如此操作;
- 即使是id也不会绝对唯一,所以建议在定位元素前多用用Inspector中的元素搜索功能查看一下;
- APP中某些元素是需要异步加载或执行的还是建议在定位元素之前加上等待时间,至于隐性还是显性的结合着的测试业务与被测对象。
- 注意同时导入了selenium、Appium包,selenium需要先导入。
元素操作
获取信息
# 需要获取按钮、文本框、输入框等控件的文本内容时使用
# 获取element控件的文本内容
element = driver.find_element_by_id("com.android.settings:id/title")
print(element.text)
# 获取元素的位置
# 返回字典,X为元素的x坐标,y为元素的y坐标
print(element.locatian)
print(element.locatian["x"])
print(element.locatian["y"])
# 获取元素的大小
# 返回字典,width为宽度,height为告诉
print(element.size)
print(element.size["width"])
print(element.size["height"])
# 获取元素的属性值
print(element.get_attribute("text"))
键盘输入
在APP中一般都会存在信息输入或交互框这类控件,如果需要往其中输入对应的测试数据,就需要用到send_keys()函数。
driver.find_element(AppiumBy.ID, 'com.tiffany.rta.debug:id/edt_customer_number').send_keys('00127')
# 清除内容
driver.find_element(AppiumBy.ID, 'com.tiffany.rta.debug:id/edt_customer_number').clear()
如果要在控件中输入中文的话,则需要在Desired Capabilities(启动参数)中加入两项参数
desired_caps['unicodeKeyboard'] = True
desired_caps['resetKeyboard'] = True
它们分别代表可以以unicode编码格式进行输入、初始化键盘状态。
模拟触控
模拟点击
# 定位元素后 使用click()
driver.find_element(AppiumBy.ID, 'com.tiffany.rta.debug:id/edt_customer_number').click()
轻敲
#模拟手指对元素或坐标的轻敲操作
#参数:
# element:元素
# X:X坐标
# y:y坐标
# 需要导入appium.webdriver.common.touch_action下的TouchAction包
from appium.webdriver.common.touch_action import TouchAction
TouchAction(driver).tap(element=None,X=None,y=None).perform()
示例 轻敲《设置》中的“WLAN”
el=driver.findelement_by_xpath("//*[contains(@text,'WLAN')]")
TouchAction(driver).tap(e1).perform()
按下和抬起
#模拟手指对元素或坐标的按下操作
#参数:
# el:元素
# X:X坐标
# y:y坐标
TouchAction(driver).press(el=None,x=None,y=None).perform()
#模拟手指对元素或坐标的抬起操作
TouchAction(driver).release().perform()
示例
TouchAction(drive).press(x=650, y=650).perform()
TouchAction(drive).press(x=650, y=650).release().perform()
等待
# 模拟手指等待,比如按下后等待5秒之后再抬起。
# 参数:
# ms:暂停的毫秒数
TouchAction(driver).wait(ms=0).perform()
# 按下指定定位的元素 停顿半秒再放开的操作
element = driver.find_element(AppiumBy.ID, 'com.tiffany.rta.debug:id/edt_customer_number')
TouchAction(drive).press(element).wait(500).release().perform()
# 按住指定坐标的元素后停顿1秒再放开的操作
TouchAction(drive).press(x=120, y=120).wait(1000).release().perform()
模拟长按
#模拟手指对元素或坐标的长按操作
#参数:
# el:元素
# X:X坐标
# y:y坐标
# duration:长按时间,毫秒
TouchAction(driver).long_press(el=None,x=None,y=None,duration=1000).perform()
element = driver.find_element(AppiumBy.ID, 'com.tiffany.rta.debug:id/edt_customer_number')
TouchAction(drive).long_press(element, duration=3000).perform()
移动
#模拟手指对元素或坐标的移动操作
#参数:
# el:元素
# X:X坐标
# y:y坐标
TouchAction(driver).move_to(el=None,x=None,y=None).perform()
# 在初始坐标处按下 等待两秒后 移动到 目标处 再放开
TouchAction(drive).press(x=120, y=120).wait(2000).move_to(x=350, y=120).release().perform()
# move_to 可以连续使用
TouchAction(drive).press(x=120, y=120).move_to(x=350, y=120).move_to(x=450, y=220).release().perform()
多点触控
如下图,模拟双指放大图片
实现步骤:
1.建立一个TouchAction,实现从坐标1到坐标2的拖动操作,但不要执行perform()方法
2.建立一个ToychAction,实现从坐标3到坐标4的拖动操作,但不要执行perform()方法
3.建立一个MultiAction类的对象,将两个TouchAction对象加入到MultiAction的对象中
4.在MultiAction对象上执行perform()函数,同时触发两个TouchAction操作
from appium.webdriver.common.multi_action import MultiAction
from appium.webdriver.common.touch_action import TouchAction
size = driver.get_window_size()
x1, y1 = size['width'] * 0.2, size['height'] * 0.2 # 第一个手指的位置
x2, y2 = size['width'] * 0.8, size['height'] * 0.8 # 第二个手指的位置
action = MultiAction(driver) \
.add(TouchAction(driver).press(x=x1, y=y1).move_to(x=x1-50, y=y1-50).release()) \
.add(TouchAction(driver).press(x=x2, y=y2).move_to(x=x2+50, y=y2+50).release()) \
.perform() # 执行动作
获取toast
toast定义:
Android中的Toast是一种简易的消息提示框。
当视图显示给用户,在应用程序中显示为浮动。和Dialog不一样的是,它不会获得焦点,无法被点击。
Toast类的思想就是尽可能不引人注意,同时还向用户显示信息,希望他们看到。
而且Toast显示的时间有限,Toast会根据用户设置的显示时间后自动消失。
图中的 用户名或密码错误,你还可以尝试4次 就是 toast
toast = driver.find_element_by_xpath('//*[@text="用户名或密码错误,你还可以尝试4次"]')
滑动
我们在做自动化测试的时候,有些按钮是需要滑动几次屏幕后才会出现,此时,我们需要使用代码来模拟手指的滑动,也就是我们将要学习的滑动和拖拽事件
swipe 滑动事件
从一个坐标位置滑动到另一个坐标位置,只能是两个点之间的滑动。
#从一个坐标位置滑动到另一个坐标位置,只能是两个点之间的滑动
#参数:
# start_x:起点x轴坐标
# start_y:起点Y轴坐标
# end_x:终点X轴坐标
# end_y:终点Y轴坐标
# duration:滑动这个操作一共持续的时间长度,单位:ms
driver.swipe(start_x,start_y,end_x,end_y,duration=None)
scroll
#从一个元素滑动到另一个元素,直到页面自动停止
# 参数:
# origin_el:滑动开始的元素
# destination_el:滑动结束的元素
driver.scroll(origin_el,destination_el)
示例
从“存储”滑动到“更多”
save_button=driver.findelement_by_xpath("//*[@text='存储']")
more_button = driver.findelementby-xpath("//*[atext='更多']")
driver.scroll(save_button,more_button)
drag_and_drop
#从一个元素滑动到另一个元素,第二个元素替代第一个元素原本屏幕上的位置
#参数:
# origin_el:滑动开始的元素
# destination_el:滑动结束的元素
driver.drag_and_drou(origin_el,destination_el)
示例
将“存储”拖拽到“更多”
save_button = driver.findelement_by_xpath("//*[@text='存储']")
morebutton=driver.findelementby-xpath("//*[@text='更多']")
driver.draganddrop(save_button,more_button)
滑动和拖拽事件的选择
滑动和拖拽无非就是考虑是否有“惯性”,以及传递的参数是“元素”还是“坐标”。
可以分成以下四种情况
有“惯性”,传入“元素” scroll
无“惯性”,传入“元素” drag_and_drop
有“惯性”,传入“坐标” swipe,并且设置较短的duration时间
无“惯性”,传入“坐标” swipe,并且设置较长的duration时间
惯性大致可以理解为,我们使用手机 在看比较长的内容时。突然向上滑动一下屏幕,文字内容会突然向下翻阅,随之会有“惯性的“慢慢停下来。
手机操作api(获取手机分辨率、截图、手机网络、通知栏)
# 获取手机分辨率
print(driver.get_window_size())
print(driver.get_window_size()["height"])
print(driver.get_window_size()["width"])
# 截图
#参数:
# filename:存储到指定路径下,并指定格式的图片
get_screenshot_as_file(filename)
示例
driver.get_screenshot_as_file(os.getcwd()+os.sep+'./screen.png')
# 获取手机网络
# 应用切景
# 视频应用在使用流量看视频的时候,大部分都会提示用户正在是否继续播放。作为测试人员,我们可能需要用自动
# 化的形式来判断是否有对应的提示。即,用流量的时候应该有提示,不用流量的时候应该没有提示。
driver.network_connection
# 网络结果对照如下图
# 设置当前网络
driver.set_network_connection()
# 输入参数使用系统提供的类型
from appium.webdriver.connectiontype import ConnectionType
# 操作通知栏
# 打开手机通知栏
driver.open_notifications()
# 注意点
# appium官方并没有为我们提供关闭通知的api,那么现实生活中怎么关闭,就怎样操作就行,比如,手指从下往上滑动,或者,按返回键
模拟按键
通过真实的按键或手机虚拟键盘进行输入框或交互框的测试数据输入。
这里区分为两种键盘,一种是模拟手机的物理按键(菜单、Home、返回等),另一种是模拟键盘按键。
使用driver.press_keycode() 或者 driver.keyevent() 两种函数。注意.press_keycode() 函数只适用于Android。
如果要使用对应的按键只需要在方法内填入相应的参数即可。
#只需要在相应方法内填入相应的参数即可。
#两种方式均可
driver.keyevent(3)
driver.press_keycode(7)
按键对应参数值
另外需要模拟长按某些物理按键的话(长按电源、长按音量),就可以使用long_press_keycode()函数来进行操作。
Appium结合PO设计模式、数据驱动、Pytest、jenkins(参考Web端的博客,或自行查阅资料)
参考目录
https://www.bilibili.com/video/BV11p4y197HQ
https://www.bilibili.com/video/BV1Fj42197Bc
https://www.bilibili.com/video/BV1R3411f7nA
https://www.bilibili.com/video/BV14D421L7J4
https://www.bilibili.com/video/BV1Ef4y1P7zQ
https://blog.csdn.net/m0_50944918/article/details/112851529
https://www.byhy.net/auto/appium/01/
https://blog.csdn.net/YJT1002/article/details/140297245
https://austin.blog.csdn.net/article/details/126364649
https://austin.blog.csdn.net/article/details/126464298
https://austin.blog.csdn.net/article/details/126554755
https://austin.blog.csdn.net/article/details/126631919
https://blog.csdn.net/m0_74105684/article/details/136592906
https://blog.csdn.net/ZL_1618/article/details/132356781