APP测试+APP自动化测试总结
APP测试
学习目标:
-
掌握基于敏捷开发的测试流程
-
掌握app的测试要点,熟悉各种专项测试的关注点
-
熟悉GT工具的使用,能使用GT工具进行对应的性能测试
一、app测试基础理论
1、app的应用架构
- app属于CS架构,是通过HTTP协义来传输数据的。 通过json的格式来传送数据的。
- web端前后交互的数据格式一HTML为主
2、敏捷开发模型介绍
-
瀑布模型(传统行业)
- 需求分析
- 设计
- 编码
- 测试
- 运行维护
优点:
1、为项目提供了按阶段划分检查点(文档)
2、当前一阶段完成后,只需要关注后续阶段。
缺点:
1、在项目各介段之间极少有反馈,出现问题没法及时处理,灵活性差
2、只有在项目结束交付上线时才能看到最终的结果
3、需要太多的文档来驱动项目进行。影响项目的效率。
结论:采用传统的瀑布模型最大的问题是开发的周期长,迭代的速度慢。
-
敏捷开发:
概念:以用户的需求为核 心,采用迭代、循序渐近的方法进行软件开发
在敏捷开发过程当,软件项目在构建初期会被切分成不同的子系统以及不同的失代,各个子项目的成果经过测度,具备可视,可集成和可运行的特征。
二、[学车不] app测试
账号:18325539630
密码:Mike123456
1、app测试要点
对于APP项目的测试,一般是进行系统测试。
系统测试的要点一般包括如下这些方面:
- 功能测试
- 兼容性测试
- 安装、卸载、升级测试
- 交叉事件测试
- PUSH测试
- 性能测试
- CPU
- 内存
- 流量
- 电量
- 流畅度
- 启动速度
- 用户体验测试
- 稳定性测试
三、专项测试
1、业务功能测试
- 根据软件说明,设计文档或用户需求验证App的各个功能的实现。
2、兼容性测试 (专项)
- 系统 1、android 2、IOS
- 手机系统的版本 覆盖主流 https://tongji.baidu.com/research/app
- android 对应的主流版本
- IOS 对应的主流版本
- 品牌-机型 覆盖主流 https://tongji.baidu.com/research/app
- android 华为、小米、vivo等
- IOS 苹果
- 屏幕分辨率 覆盖主流 https://tongji.baidu.com/research/app
3、安装、卸载、升级测试
- 正常场景:
1、在不同的操作系统、不同的手机品版和版本上安装
2、从不同的渠道下载app进行测试
3、不同的安装路径,安装在手机的内存卡或者是SD卡(非必要)
- 异常场景:
4、安装时出现异常(关机、断网),恢复后能否继续安装
5、安装时存储空间不够或者内存不足
6、安装时点出取消再安装
7、安装之后再次覆盖安装
8、低版本覆盖安装高版本
-
卸载
正常卸载:长按app正常删除卸载、通过第三方工具进行卸载
异常卸载:app正在运行卸载、取消卸载、卸载关机、卸载之后数据是否保留
-
升级
正常升级: 从低版本升级到高版本,从app内部升级, 从app应用商城升级
异常升级:跨版本升级, 关机,内存不足,电量不足
升级提示
升级之后数据的检查
4、交叉事件测试
概念:交叉测试又称为冲突测试,或者干扰测试
交叉事件的关注点:
1、app运行时接打电话
2、app运行时收发短信
3、app运行时收到推送通知
4、app运行时接到视频通话
5、app运行连接蓝牙
6、app运行时切换网络、切换应用
7、app运行时旋转屏幕
5、PUSH消息测试
- 消息推送的场景:
- 新闻资讯类通知, 让用户实时获取到自己感兴趣的新闻,从而增加用户的粘性
- 商城类通知, 让用户获取到商城的促销活动,提高用户的成交率
- 流程类的通知, 让用户及时获取处理工作的内容。
- 推送原理: 是由服务器通过推送的服务将对应的消息推送到app端。 是一个长连接的状态。
- 推送服务器: 使用的是第三方的推送服务器。(极光或者信鸽)
- 手机厂商会自己的推送服务器。
- 中小企业不会自己搭建推送服务器,一般使用的都是第三方的推送服务器
- push消息推送的关注点
- PUSH消息推送是否按指业务规则发送.
- 当PUSH推送时,检查是否按特定用户去进行推送.
- 设置不接收推送消息时,确认是否正常
- 推送通知的跳转是否正常
- 推送消息的打开及展示
- 包括app是否运行,都需要去关注推送消息能否收到。
6、性能测试
1、打开USB调式, 点击“系统应用”--“设置”, 在设置 的最下方选择“关于平板电脑”,在关于平板电脑中点击“版本号”,直接提示开发者选项已打开。
2、返回到设置 菜单页面时,可以 看到 “开发者选项”这个菜单。点击进入到开发者选项, 需要打开 USB调试 以及指针位置 这两个选项。
3、开启超级管理员访问权限
- 点击“系统应用”--“文件管理器”, 在文件管理器的左上方有三横杆的按钮,在弹出的页面中点击左下方的 齿轮 按钮,进入到设置页面之后,选择 “常规设置”---“访问模式”,将访问模式更改为超级管理员访问模式。
6.1 性能工具介绍及安装
-
GT随身调 android版是由腾讯公司开发的性能测试平台。直接运行在手机上面的。
-
可以通过GT工具进行基础的性能测试:内存、CPU、电量、网络流量、流畅度,可以以绘制图表的形式显示出指标的相关数据
-
GT工具提供了查看日志的功能。可以通过查看相关日志来分析和定位app功能异常以及crash等问题
6.2 性能工具使用
-
打开GT工具,在AUT界面选择被测试的app以及对应的性能指标
-
设置参数,进入到参数页面,点击右上角的"编辑"按钮,拖动想要测试的参数到已关注区域,而且要勾选。
勾选之后,点击上方的红色 录制按钮。
-
执行测试之前,进入到日志界面,开启logcat的日志记录功能。
-
如果要进行电量或流量的性能测试需要进入到插件页面进行设置。
-
返回到AUT界面,在上面点击“启动”或者“running” 来启动被测试的app
-
针对app进行相关的业务操作
-
操作完成之后,再进入到GT工具,查看性能参数的数据。
6.3 CPU测试
GT工具提供了两个CPU的监控指标:CPU和jiffes
CPU指标就是指当前手机中cpu的整体使用率
用户态:cpu处于应用程序执行的时间
系统态:表示的是系统内核执行的时间
空闲态:表示空闲系统进程执行的时间
cpu使用率 = cpu空闲态/cpu的总的执行时间
jiffief:
表示的是开机以来,程序消耗的CPU时间片的总数
CPU问题的影响:
1、CPU使用长时间处于90%以上 (70 80 )
2、手机发热、耗电量增加
3、反应变慢,引起ANR(假死状态)
操作步骤:
1、打开GT工具,进入到AUT页面,选择测试的app,勾选CPU性能指标
2、进入到参数界面,配置CPU参数选项,然后进行勾先,点击录制
3、进入到日志界面,打开logcat记录日志
4、返回到AUT界面,启动app
5、针对app进行相关的业务操作(实际工作当中,操作时间会比较长)
6、返回到GT工具界面,查看相关的参数数据。
6.4 内存测试
PSS和private dirty
private dirty(私有内存):
进程独占的内存,也就是进程销毁时可以回收的内存容量.
PSS(实际使用内存):
将跨进程的共享内存也加入进来,进行按比列计算PSS。就能够准确的表示进程占用的实际物理内存。
常见问题:
1、内存泄漏
内存泄漏(memory leak):当程序运行时申请了对应的内存空间,而当程序销毁时并没有释放对应的内存空间。
2、内存溢出
内存溢出 (out of memory):是指程序在申请内存空间时,没有足够的内存空间供其使用。
-
内存问题产生的影响
1、程序实际使用的内存PSS会不停的增长
2、程序会出现闪退(crash)
内存的指标根据不同的手机配置、以及不同的公司,指标值是不一样的。
-
内存操作步骤:
-
打开GT工具,选择对应的被测app, 勾选内存指标(PSS和private dirty)
-
进入到参数界面,编辑参数,勾选对应参数,并点击录制按钮
-
进入到日志界面,开启logcat,记录日志信息
-
回到AUT界面,点击 启动按钮,启动被测试的app
-
针对启动的app进行相关的业务功能操作(时间一般也会在几个小时左右。)
-
操作完成,回到GT工具的参数界面,查看获取到的参数数据。
-
6.5 流畅度测试
GT工具提供了流畅度的监控指标:FPS
FPS是指人的肉眼能够看到的画面每一秒帧数
效果:想要达到流畅的效果,至少每秒的帧数要达到24帧
每秒的帧数越高流畅度就越好
如果想要达到最佳的流畅度需要达到每秒60帧
当页面静止不动时,FPS的值显示的是0
测试时间:15-30分钟
操作步骤:
1、打开GT工具,进入到AUT界面,选择被测试的app
2、进入到参数界面,点击编辑拖动FPS参数到已关注参数中,勾选之后,点击录制
3、进入到日志界面,开启logcat记录日志信息
4、返回到AUT界面,点击启动,打开被测试的app
5、针对被测app进行相关的业务操作
6、返回到参数界面查看参数数据
6.6 流量测试
GT工具里面提供了一个监控流量的指标:NET
流量:手机在访问网络过程当所产生的上传和下载的数据(报文)就称为流量
-
常用流量测试方法:
-
抓包测试法
通过抓包工具将所有的网络应用数据包,全部抓取到并保存到某个文件中,进行分析的过程 。
wireshark所有协议的报文,sniffer也可以抓所有的报文,
tcpdump命令可以抓所有的报文
-
统计测试法
获取的是某一个应用程序获取的数据报文,统计出对应的流量。
-
-
GT工具测试步骤:
打开GT进入到AUT界面,选择被测试的app,勾选NET指标
进入到参数界面,点击编辑,拖选 NET参数,勾选并点击录制
进入到日志界面,开启Logcat记录日志信息
进入到插件界面,选择“抓包”,再点击“开始”
返回到AUT界面,点击“启动”,启动测试app
针对启动的app进行相关业务操作
返回到参数界面,停止录制,再返回到插件界面,点击“抓 包”,再点“停止”
-
流量的优化:
数据压缩 在HTTP协议中可以通过此字段将数
据进行压缩,减少数据容量。content-encoding: gzip
不同的数据格式的采用 json lxml 数据格式
控制访问的频次 通过异步加载的方式来加载数据。
只获取必要的数据
缓存机制 懒加载 将多个图片放在同一张图片里面,一起加载。
6.7 电量测试
GT工具当中提供了电量的监控指标:电流、电压,电量跟温度
就是指移动设备电量消耗快慢的一种测试方法。一般用平均电流来
衡量电量的消耗速度。
常见的耗电场景:
定位,GPS
网络传输
蓝牙
屏幕的亮度
GT工具只能特定类型的机型进行电量的测试。
可换其他性能测试工具进测试,也可以使用对比方式进行测试(拿
同类型的产品,在同样的手同样的场景下进行对比测试。)
6.8 用户体验测试
用户体验主要是跟app的界面有关。
-
UI界面测试 包括界面的设计、界面元素框架、结构、颜色、布局、图片、按钮选中的一些效、文字的内容。
-
易用性测试 菜单的层次、完成业务操作的步骤是否过多, 点击按钮的范围 是不是合适,包括返回键的操作
-
横竖屏测试 横屏之后,页在的表格是不是能正常的显示。
-
关注手机上的其他辅助功能 放大字体
6.9 弱网测试
7、用户体验测试
8、稳定性测试
app自动化测试
一、app自动化框架介绍
1、常用自动化框架介绍
-
Robtium
-
macaca
-
Appium
是一款国外开源的自动化测试框架
适用平台:android、IOS
支持的语言:java\js\php\python\C#\ruby
社区活跃、资料丰富
-
appium的特点:
-
开源
-
支持Native App(全部android sdk的java代码生成) 原生的app如果页面有变更,就得发一版本,提交到应用商城去审核
-
Web App(都是由HTML5生成的) 访问速度慢。H5的代码以及元素信息
-
Hybird APP(既有native app也有H5的页面)混合app 是当前工作中用得最多的
支持andorid 、IOS
支持跨平台、支持windows、linux、macos
支持多语言 java js python C# ruby
-
2、appium介绍
2.1 appium自动化原理
通过此图可以知道app的自动化环境需要以下工具:
- appium服务器
- 基于python的appium客户端(appium-client-python)
- adb(adb集成在android-sdk中)
- JDK
二、自动化测试环境搭建
1、java安装
- 双击可执行文件,安装过程中建议不要将安装目录设置在含有中文的目录。建议不要发装在系统盘中。
- 验证: 在DOS命令行中输入 java -version 如果能看下图所显示的信息就是正确的。
2、android SDK安装
2.1 androidSDK安装
下载链接: https://android-sdk.en.softonic.com/?ex=MOB-593.7
-
安装步骤:
-
解压android-sdk的压缩包文件
-
将解压的目录复制到某一个文件夹下,文件夹的路径也不要包含 中文
-
添加相应的环境变量(以下三个目录)
-
D:\Program Files\android-sdk\tools
uiautomatorviewer.bat工具可以用来查看app的元素信息
-
D:\Program Files\android-sdk\platform-tools
adb.exe 此工具用来连接手机
-
D:\Program Files\android-sdk\build-tools\25.0.0
aapt.exe 可以获取app的包名和启动名
-
-
-
验证:
1、在DOS命令行中输入 uiautomatorviewer 如果能显示以下图片,就说明是正常的。
2、在DOS命令行中输入: adb ,如果 能出现以下图片,就说明是正常.
3、在DOS命令行中输入: aapt , 如果能出现发下图片,就说明是正常的
3、模拟器安装(略过)
4、appium服务器安装
4.1 appium安装
- 双击appium服务器的可执行文件,默认安装在C盘。
4.2 appium验证
-
启动服务之前,需要先配置jdk以及android-sdk的目录。
-
启动服务,如果能看到以下图片信息,说明安装正常
5、appium-client-python安装
-
安装方式
-
离线 解压对应的安装包文件,进到解压目录下执行 python setup.py install
-
在线 pip install Appium-Python-Client
-
pycharm
-
-
验证是否安装
-
pip show Appium-Python-Client
-
pycharm
-
三、adb工具
1、adb工具构成及原理
- adb 包含 了三个部分
- adb 客户端 ---用来下发adb的指令工具
- Server 服务端 ---adb.exe执行之后的进程,表示adb的服务端,通过服务端与手机上的adb守护进程进行 通信
- adb守护进程 --- 随着android系统的启动而启动,当android系统关闭之后它才会关闭。
2、adb常用命令
2.1 adb常用命令(常看设备、启动关闭adb服务)
如果是真机,不要 使用一带多接头的数据线,否则找不到手机设备
-
adb devices ---查看手机的设备ID名称以及状态
-
emulator-5554 device
-
emulator-5554---表示的是手机设备的ID名称, device---表示设备处于在线状态,
-
如果不在线显示的是offline
-
如果adb服务没有启动,下发该命令时,会自动的去启动adb的服务
-
-
-
adb start-server ---启动adb服务
-
adb kill-server ---关闭adb 服务
关闭adb 服务后,也可以直接通过adb devices 命令启动
2.2 获取包名和界面名
- 包名: app包名 ,通过app的包名来区分不同的app,app包名是唯 一的
- 界面名(启动名): 相当于web页面当中的链接地址,在app当中,每个界面都有一个名字
原因:自动化过程当,需要通过app的包名和界面名来启动app。
-
操作步骤: adb命令
- 在手机或者模拟器上面打开app
- windows命令一:adb shell dumpsys window windows |findstr mFocusedApp
- windows命令二: adb shell dumpsys window |findstr "usedApp"
- LINUX/MacOS命令一: adb shell dumpsys windowwindows | grep mFocusedApp
- LINUX/MacOS命令二: adb shell dumpsys window |grep "usedApp"
示例: com.android.settings/.Settings
com.android.settings是包名, .Settings是界面名 通过 / 分隔包名和界面名
-
通过aapt获取app的包名和界面名
-
aapt dump badging
D:\BaiduNetdiskDownload\apptools\apk\xuechebu.apk
后面表示的是app安装包的路径及名称
包名: package: name='com.bjcsxq.chat.carfriend' #
package:name 后面的字符串表示的是app的包名
界面名: launchable-activity:
name='com.bjcsxq.chat.carfriend.module_main.activity.S
plashActivity' launchable-activity: name后面的字符串是
界面
-
2.3 安装卸载app
-
app安装 ----- adb install 路径/app安装包名称
-
app卸载 ------ adb uninstall 包名
2.4 上传下载文件
-
上传 将电脑上的文件上传到手机
adb push 电脑上的文件路径 手机的路径
例子:adb push ./monkey.txt /sdcard
-
下载文件 从手机上下载文件到本地
adb pull 手机的文件路径 电脑的文件夹路径
例子:adb pull /sdcard/monkey.txt D:\opt
2.5 查看日志信息
为什么要获取日志信息:用来给开发定位问题。
adb logcat 来查看相关的日志信息
2.6 测试app的启动速度(性能测试)
-
测试app启动速度的命令:
adb shell am start -W 包名/界面名
adb shell am start -W com.baidu.homework/.activity.user.passport.ChoiceLoginModeActivity
该命令获取3个关键指标:
ThisTime:表示一连串启动Activity的最后一个Activity启动耗时,一般会<=TotalTime时间。
TotalTime:应用的启动时间,包括创建进程、App初始化、Activity初始化到界面显示。(开发者需要优化的耗 时)
WaitTime:前一个应用activity pause的时间+TotalTime
- 需要大家关注的是TotalTImie的时间值,那么在实际的测试过程中,会进行多次测试,然后取平均值。
3、稳定性测试 (8小时)
-
monkey 集成在adb工具当中,主要用来做稳定性测试用的,
monkey是通过java语言编写的一种稳定性测试工具。
主要用来测试app会不会出现crash(崩溃)的情况。
相当于让一只猴子来随机操作app,所有的操作都有可能出现,
长时间的操作来测试app会不会出现问题。
-
monkey常用的参数
-
-p 参数 对指定的app进行随机操作
adb shell monkey -p com.baidu.homework 100 (100次随机事件,不是100次点击,有可能是长按操作,滑屏操作等)
-
-v 参数 表示的是记录信息的级别
level 0:adb shell monkey -p com.baidu.homework -v 100 默认级别
level 1: adb shell monkey -p com.baidu.homework -v -v 100 打印出来的信息会比较详细,只打印跟本程序相关的日志信息
level 2: adb shell monkey -p com.baidu.homework -v -v-v 100 打印出来的信息会更多,会显示出其他程序运行的信息
-
-s 用于指定伪随机数。如果两次的伪随机数相同,那么两次的操作步骤、流程、操作事件完全一样。
主要的作用,就是用来复现上次的问题
adb shell monkey -p com.baidu.homework -v -v -s 10 100
-
--throttle 用于指定随机事件的间隔时间, 单位是毫秒
adb shell monkey -p com.baidu.homework -v -v --throttle 3000 -s 10 100
组合使用:
adb shell monkey -p com.baidu.homework --throttle 500 --
pct--touch 10 --pct-motion 50 -v -v -s 100 300> log.log
--pct--touch 10 触模(10表示的是整个随机同件中的百分比)
--pct-motion 50 滑屏(50表示的是整个随机同件中的百分比)
-
-
日志分析
如果在日志里面出现了 ANR(application not responsing)
如果日志中出现了Exception,可能程序崩溃。
adb 操作命令
-
手势操作命令
-
模拟点击事件
adb shell input tap x y # x y表示的是坐标点 参数之间用空格隔开
-
模拟滑屏事件(参数之间用空格隔开)
adb shell input swipe startx starty endx endy
startx, starty 表示的是起始点坐标,endx,endy表示的是终点坐标
-
模拟键盘操作
adb shell input keyevent 键值 (3 表示的HOME键 4 表示的返回键 66表示的回车键)
-
模拟输入操作
adb shell input text 内容 内容表示要输入的内容,另外输入的内容不能是中文
-
四、入门示例(APP自动化)
import time
# 导入webdriver
from appium import webdriver
# 初始化app的配置信息
caps={} #定义字典参数
caps['automationName'] = 'UiAutomator2' #测试框架名称
caps['platformName']='Android' #表示的是android 或者IOS系统
caps['platformVersion']='5.1.1' #操作系统的版本
caps['deviceName']='emulator-5554' #虚拟设备号,表示的是设备的ID名称(如果只有一个设备可以用****来替代)caps["deviceName"] = "****"
caps['appPackage']='com.android.settings' #表示的是app的包名
caps['appActivity']='.Settings' #界面名---可以理解被测程序
driver=webdriver.Remote('http://127.0.0.1:4723/wd/hub',caps)
#或者 -driver=WebDriver('http://127.0.0.1:4723/wd/hub',caps)
#要导入包from appium.webdriver.webdriver import WebDriver
time.sleep(2)
driver.quit()
五、uiautometorview工具使用
-
通过uiautomatorviewer工具可以查看app的元素信息。
查看元素信息:
示例:先报存当前页面的元素信息,(如保存到桌面),然后在打开文件 就可以实现在代码运行中去查看定位了
-
如果出现如下错误:
需要重启adb服务。获取app页面信息时不能正在运行代码,会占用adb服务。
- 为了提高效率,在android sdk的 tools目录下,将uiautomatorviewer.bat复制一份出来,并修改为ui.bat就OK了。后续直接在dos中输入ui就可以打开了
六、appium基础操作
1、通过appium启动app
- driver.start_activity("包名",”界面名“)
driver.start_activity("com.baidu.homework",".activity.user.passport.ChoiceLoginModeActivity")
示例:在启动手机设置页面后,继续启动作业班APP
import time
# 导入webdriver
from appium import webdriver
caps={
"platformName":"Android",
"platformVersion":"5.1.1",
"deviceName":"emulator-5554",
"appPackage":"com.android.settings",
"appActivity":".Settings"
}
driver=webdriver.Remote('http://127.0.0.1:4723/wd/hub',caps)
time.sleep(2)
#启动另外一个APP---作业班apk (效果:在启动手机设置页面后,继续启动作业班APP)
driver.start_activity("com.baidu.homework",".activity.index.IndexActivity")
time.sleep(2)
driver.quit()
2、获取包名和界面名
-
获取当前驱动对象的包名和界面名
driver.current_package 获取当前脚本运行中的app的包名
driver.current_activity 获取当前脚本运行中的app的界面名
import time
# 导入webdriver
from appium import webdriver
caps={
"platformName":"Android",
"platformVersion":"5.1.1",
"deviceName":"emulator-5554",
"appPackage":"com.android.settings",
"appActivity":".Settings"
}
driver=webdriver.Remote('http://127.0.0.1:4723/wd/hub',caps)
time.sleep(2)
#启动另外一个APP---作业班apk (效果:在启动手机设置页面后,继续启动作业班APP)
driver.start_activity("com.baidu.homework",".activity.index.IndexActivity")
print(driver.current_activity)
print(driver.current_package)
time.sleep(2)
driver.quit()
.activity.index.IndexActivity
com.baidu.homework
Process finished with exit code 0
3、关闭app及关才驱动
-
关闭app
driver.close_app() 不需要跟参数
-
关闭驱动
driver.quit()
-
区别:
关闭app之后,可以再使用其他代码启动新的app
关闭驱动,那么代码与appium服务器之间的连接已经断,开不能再做任何的操作。
import time
# 导入webdriver
from appium import webdriver
# 初始化app的配置信息
caps={}
caps['automationName'] = 'UiAutomator2' #测试框架名称------这一个参数去掉不报错 可以运行
caps['platformName']='Android' #表示的是android 或者IOS系统
caps['platformVersion']='5.1.1' #操作系统的版本
caps['deviceName']='emulator-5554' #虚拟设备号,表示的是设备的ID名称(如果只有一个设备可以用****来替代)#caps["deviceName"] = "****"
caps['appPackage']='com.android.settings' #表示的是app的包名
caps['appActivity']='.Settings' #界面名---可以理解被测程序
driver=webdriver.Remote('http://127.0.0.1:4723/wd/hub',caps)
#关闭当前APP
driver.close_app()
#启动另一个APP--作业班APP
driver.start_activity("com.baidu.homework",".activity.index.IndexActivity")
time.sleep(6)
#退出驱动
driver.quit()
4、安装卸载app以及判断是否安装app
- 安装app driver.install _app(apk路径)
- 卸载app driver.remove_app(app包名)
import time
# 导入webdriver
from appium import webdriver
# 初始化app的配置信息
caps={}
caps['automationName'] = 'UiAutomator2' #测试框架名称------这一个参数去掉不报错 可以运行
caps['platformName']='Android' #表示的是android 或者IOS系统
caps['platformVersion']='5.1.1' #操作系统的版本
caps['deviceName']='emulator-5554' #虚拟设备号,表示的是设备的ID名称(如果只有一个设备可以用****来替代)#caps["deviceName"] = "****"
caps['appPackage']='com.android.settings' #表示的是app的包名
caps['appActivity']='.Settings' #界面名---可以理解被测程序
driver=webdriver.Remote('http://127.0.0.1:4723/wd/hub',caps)
#关闭当前APP
driver.close_app()
time.sleep(2)
#安装263.APk
driver.install_app(r"D:\A_学习\09、UI自动化测试及黑马头条项目实战\工具\UI自动化\app自动化工具集合\apk\263.apk")
#卸载263.apk
driver.remove_app("com.em.mobile")
time.sleep(2)
#退出驱动
driver.quit()
-
判断手机是否安装app driver.is_app_installed("包名")
返回值:True 有安装app 或者False 没有安装app
-
优化---卸载apk代码优化:如果没有安装263.apk,那就安装;如果安装了263.apk,那就卸载了重新安装
if driver.is_app_installed("com.em.mobile"): driver.remove_app("com.em.mobile") driver.install_app(r"D:\A_学习\09、UI自动化测试及黑马头条项目实战\工具\UI自动化\app自动化工具集合\apk\263.apk")
import time
# 导入webdriver
from appium import webdriver
# 初始化app的配置信息
caps={}
caps['automationName'] = 'UiAutomator2' #测试框架名称------这一个参数去掉不报错 可以运行
caps['platformName']='Android' #表示的是android 或者IOS系统
caps['platformVersion']='5.1.1' #操作系统的版本
caps['deviceName']='emulator-5554' #虚拟设备号,表示的是设备的ID名称(如果只有一个设备可以用****来替代 #caps["deviceName"] = "****"
caps['appPackage']='com.android.settings' #表示的是app的包名
caps['appActivity']='.Settings' #界面名---可以理解被测程序
driver=webdriver.Remote('http://127.0.0.1:4723/wd/hub',caps)
#关闭当前APP
driver.close_app()
time.sleep(2)
if driver.is_app_installed("com.em.mobile"):
driver.remove_app("com.youdao.note")
driver.install_app(r"D:\A_学习\09、UI自动化测试及黑马头条项目实战\工具\UI自动化\app自动化工具集合\apk\263.apk")
time.sleep(6)
#退出驱动
driver.quit()
5、将应用置于后台运行
- driver.background_app(seconds) # seconds 表示的是将app置于后台运行多少秒的时间
from appium import webdriver
# 初始化app的配置信息
caps={}
caps['automationName'] = 'UiAutomator2' #测试框架名称------这一个参数去掉不报错 可以运行
caps['platformName']='Android' #表示的是android 或者IOS系统
caps['platformVersion']='5.1.1' #操作系统的版本
caps['deviceName']='emulator-5554' #虚拟设备号,表示的是设备的ID名称(如果只有一个设备可以用****来替代) #caps["deviceName"] = "****"
caps['appPackage']='com.android.settings' #表示的是app的包名
caps['appActivity']='.Settings' #界面名---可以理解被测程序
driver=webdriver.Remote('http://127.0.0.1:4723/wd/hub',caps)
#先打开“设置页面”,然后放在后台运行5秒钟,重新打来设置页面
driver.background_app(5)
time.sleep(3)
#退出驱动
driver.quit()
七、元素定位
1、定位单个元素
1.1 通过ID定位元素
-
通过元素的resource-id来进行元素定位
driver.find_element_by_id(resource_id的值)
1.2 通过class_name定位元素
-
通过元素的class属性值来进行元素定位
app中,class的值始终都只有一个。
driver.find_element_by_class_name(class)
1.3 通过xpath定位元素
-
通过xpath的元素属性来进行元素定位
driver.fifind_element_by_xpath("//*[@text='value']")
单个元素定位不到会报错。
示例:
import time
# 导入webdriver
from appium import webdriver
# 初始化app的配置信息
caps={}
caps['automationName'] = 'UiAutomator2' #测试框架名称------这一个参数去掉不报错 可以运行
caps['platformName']='Android' #表示的是android 或者IOS系统
caps['platformVersion']='5.1.1' #操作系统的版本
caps['deviceName']='emulator-5554' #虚拟设备号,表示的是设备的ID名称(如果只有一个设备可以用****来替代)
caps['appPackage']='com.android.settings' #表示的是app的包名
caps['appActivity']='.Settings' #界面名---可以理解被测程序
driver=webdriver.Remote('http://127.0.0.1:4723/wd/hub',caps)
# 找到“更多”按钮并点击(XPATH)
driver.find_element_by_xpath("//*[@text='更多']").click()
time.sleep(2)
# 找到 飞行模式的 开关,并点击(ID)
driver.find_element_by_id("android:id/switchWidget").click()
time.sleep(2)
# 找到返回按钮并点击(class)
driver.find_element_by_class_name("android.widget.ImageButton").click()
time.sleep(3)
#退出驱动
driver.quit()
通过显示等待定位元素(重点)
(1)用到po模式(封装显示登录)
- 单独一个文件封装显示登录
#定义一个获取元素的方法
from selenium.webdriver.support.wait import WebDriverWait
def get_element(driver,find_type,value):
wait=WebDriverWait(driver,10,1)
element=wait.until(lambda x:x.find_element(find_type,value))
return element
优化代码:
def get_element(driver, element): # element 表示的元素定位的值
wait = WebDriverWait(driver, 10, 1)
element = wait.until(lambda x: x.find_element(element[0], element[1]))
return element
- 调用
import time
from selenium.webdriver.common.by import By
from phonetest.demo2 import get_element
# 导入webdriver
from appium import webdriver
# 初始化app的配置信息
caps={}
caps['automationName'] = 'UiAutomator2' #测试框架名称------这一个参数去掉不报错 可以运行
caps['platformName']='Android' #表示的是android 或者IOS系统
caps['platformVersion']='5.1.1' #操作系统的版本
caps['deviceName']='emulator-5554' #虚拟设备号,表示的是设备的ID名称(如果只有一个设备可以用****来替代)
caps['appPackage']='com.android.settings' #表示的是app的包名
caps['appActivity']='.Settings' #界面名---可以理解被测程序
driver=webdriver.Remote('http://127.0.0.1:4723/wd/hub',caps)
# 找到“更多”按钮并点击(XPATH)
more_element=[By.XPATH,"//*[@text='更多']"]
get_element(driver,more_element[0],more_element[1]).click()
# 找到 飞行模式的 开关,并点击(ID)
air_element=[By.ID,"android:id/switchWidget"]
get_element(driver,air_element[0],air_element[1]).click()
# 找到返回按钮并点击(class)
return_element=[By.CLASS_NAME,"android.widget.ImageButton"]
get_element(driver,return_element[0],return_element[1]).click()
time.sleep(3)
#退出驱动
driver.quit()
- 优化显示等待的封装脚本
def get_element(driver, element):
wait = WebDriverWait(driver, 10, 1)
element = wait.until(lambda x: x.find_element(element[0], element[1]))
return element
# 找到“更多”按钮并点击(XPATH)
more_element=[By.XPATH,"//*[@text='更多']"]
get_element(driver,more_element).click()
- 继续优化显示登录脚本(星号表示拆包)
def get_element(driver, element):
wait = WebDriverWait(driver, 10, 1)
element = wait.until(lambda x: x.find_element(*element)
return element
(2)不用po模式
import time
# 导入webdriver
from appium import webdriver
# 初始化app的配置信息
from selenium.webdriver.support.wait import WebDriverWait
caps={}
caps['automationName'] = 'UiAutomator2' #测试框架名称------这一个参数去掉不报错 可以运行
caps['platformName']='Android' #表示的是android 或者IOS系统
caps['platformVersion']='5.1.1' #操作系统的版本
caps['deviceName']='emulator-5554' #虚拟设备号,表示的是设备的ID名称(如果只有一个设备可以用****来替代)
caps['appPackage']='com.android.settings' #表示的是app的包名
caps['appActivity']='.Settings' #界面名---可以理解被测程序
driver=webdriver.Remote('http://127.0.0.1:4723/wd/hub',caps)
# 找到“更多”按钮并点击(XPATH)
WebDriverWait(driver,10,1).until(lambda x:x.find_element_by_xpath("//*[@text='更多']")).click()
# driver.find_element_by_xpath("//*[@text='更多']").click()
# time.sleep(2)
# 找到 飞行模式的 开关,并点击(ID)
WebDriverWait(driver,10,1).until(lambda x:x.find_element_by_id("android:id/switchWidget")).click()
# driver.find_element_by_id("android:id/switchWidget").click()
# time.sleep(2)
# 找到返回按钮并点击(class)
WebDriverWait(driver,10,1).until(lambda x:x.find_element_by_class_name("android.widget.ImageButton")).click()
# driver.find_element_by_class_name("android.widget.ImageButton").click()
time.sleep(3)
#退出驱动
driver.quit()
2、定位一组元素
driver.find_elements_by_id(resource_id)
driver.find_elements_by_class_name(class_name)
driver.find_elements_by_xpath(xpath)
driver.find_elements(By.ID, value)
返回的值是一个列表,如果没有找到,说明列表是空值,可以通过下标来使用其中的元素对象,下标是从0开始。
- uiautometorview工具没发确认重复的数据是第一个下标,只能肉眼看
import time
# 导入webdriver
from appium import webdriver
from selenium.webdriver.common.by import By
# 初始化app的配置信息
caps={}
caps['automationName'] = 'UiAutomator2' #测试框架名称------这一个参数去掉不报错 可以运行
caps['platformName']='Android' #表示的是android 或者IOS系统
caps['platformVersion']='5.1.1' #操作系统的版本
caps['deviceName']='emulator-5554' #虚拟设备号,表示的是设备的ID名称(如果只有一个设备可以用****来替代)
caps['appPackage']='com.android.settings' #表示的是app的包名
caps['appActivity']='.Settings' #界面名---可以理解被测程序
driver=webdriver.Remote('http://127.0.0.1:4723/wd/hub',caps)
# 找到“更多”按钮并点击(id)
elements=driver.find_elements(By.ID,"com.android.settings:id/title")
elements[1].click()
time.sleep(3)
#退出驱动
driver.quit()
八、元素操作
1、点击操作
element.click() 针对元素进行点击操作
2、清空和输入操作
element.clear() 针对元素进行清空操作
element.send_keys("value") 针对元素进行输入操作
3、输入的封装
# 为了保证代码的健壮性,确定输入的内容一定不会出错,所以在输入前做了一次清除。
def input_text(element,text):
'''
:param element: 表示的是元素对象
:param text: 表示的是要输入的内容
:return:
'''
#清除元素中的文本内容
element.clear()
# 输入文本内容
element.send_keys(text)
import time
# 导入webdriver
from appium import webdriver
from selenium.webdriver.common.by import By
from phonetest.demo2 import get_element, input_text
# 初始化app的配置信息
caps={}
caps['automationName'] = 'UiAutomator2' #测试框架名称------这一个参数去掉不报错 可以运行
caps['platformName']='Android' #表示的是android 或者IOS系统
caps['platformVersion']='5.1.1' #操作系统的版本
caps['deviceName']='emulator-5554' #虚拟设备号,表示的是设备的ID名称(如果只有一个设备可以用****来替代)
caps['appPackage']='com.android.settings' #表示的是app的包名
caps['appActivity']='.Settings' #界面名---可以理解被测程序
driver=webdriver.Remote('http://127.0.0.1:4723/wd/hub',caps)
#在设置 点击 搜索按钮
search_element=[By.ID,"com.android.settings:id/search"]
get_element(driver,search_element[0],search_element[1]).click()
#在搜索框中输入wifi
input_element=[By.ID,"android:id/search_src_text"]
a=get_element(driver,input_element[0],input_element[1])
input_text(a,"wifi")
time.sleep(3)
#退出驱动
driver.quit()
4、获取元素的信息
-
获取元素的文本内容(获取的是元素text属性的内容)
element.text
-
获取元素的位置
element.location
返回的值是一个字典,字典中包含x和y , x和y表示的是元素在手机屏幕左上角的点的坐标
-
获取取元素的大小
element.size 返回值是一个字典,字典中会包含 width和
height, width表示的宽度,height表示的高度
-
获取元素的属性值
element.get_attribute("attribute") # attribute表示的是属性名称
获取ID值时, attribute= “resourceId”
获取的是class的值 , attribute="className"
如果attribute = "name"时,获取的是text或者content-desc(text优先,找不到text值,再去找content-desc的值)
示例:
import time
# 导入webdriver
from appium import webdriver
from selenium.webdriver.common.by import By
from phonetest.demo2 import get_element, input_text
# 初始化app的配置信息
caps={}
caps['automationName'] = 'UiAutomator2' #测试框架名称------这一个参数去掉不报错 可以运行
caps['platformName']='Android' #表示的是android 或者IOS系统
caps['platformVersion']='5.1.1' #操作系统的版本
caps['deviceName']='emulator-5554' #虚拟设备号,表示的是设备的ID名称(如果只有一个设备可以用****来替代)
caps['appPackage']='com.android.settings' #表示的是app的包名
caps['appActivity']='.Settings' #界面名---可以理解被测程序
driver=webdriver.Remote('http://127.0.0.1:4723/wd/hub',caps)
# 找到 WLAN 元素
a=driver.find_element_by_id("com.android.settings:id/title")
# 获取 WLAN 菜单的文本内容
print(a.text)
# 获取 WLAN 的位置信息
print(a.location)
# 获取 WLAN 元素的大小
print(a.size)
# 获取 WLAN 元素className的属性值
print(a.get_attribute("className"))
time.sleep(3)
#退出驱动
driver.quit()
-----------------------------------------------------------------------------------------------------------
WLAN
{'x': 216, 'y': 457}
{'height': 73, 'width': 152}
android.widget.TextView
Process finished with exit code 0
5、初始化:中文输入的处理
在初始化配置中增加两个参数(目前不加也可以,遇到了在加这两个参数把)
"resetKeyboard": True, # 重置设备的输入键盘
"unicodeKeyboard": True # 采用unicode编码输入
import time
# 导入webdriver
from appium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from phonetest.demo2 import get_element, input_text
# 初始化app的配置信息
caps={}
caps['automationName'] = 'UiAutomator2' #测试框架名称------这一个参数去掉不报错 可以运行
caps['platformName']='Android' #表示的是android 或者IOS系统
caps['platformVersion']='5.1.1' #操作系统的版本
caps['deviceName']='emulator-5554' #虚拟设备号,表示的是设备的ID名称(如果只有一个设备可以用****来替代)
caps['appPackage']='com.android.settings' #表示的是app的包名
caps['appActivity']='.Settings' #界面名---可以理解被测程序
caps['resetKeyboard']=True # 重置设备的输入键盘
caps['unicodeKeyboard']=True # 采用unicode编码输入
driver=webdriver.Remote('http://127.0.0.1:4723/wd/hub',caps)
#搜索按钮 ID=com.android.settings:id/search
WebDriverWait(driver,10,1).until(lambda x:x.find_element_by_id("com.android.settings:id/search")).click()
#搜索框 ID= android:id/search_src_text
WebDriverWait(driver,10,1).until(lambda x:x.find_element_by_id("android:id/search_src_text")).send_keys("中文")
time.sleep(3)
#退出驱动
driver.quit()
6、初始化:区分首次打开还是非首次打开
- 就是安装打开APP 会勾选协议
- 就是之前登录了,下次就不用登录了
没必要加,不加"noReset": True的话,每次运行脚本都会出现协议页面
"noReset": True # 用来记住app的session,如果有登陆或做过初始化的操作,为True时,后面不需要再操作
#学初不APP
import time
# 导入webdriver
from appium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
# 初始化app的配置信息
caps={}
caps['automationName'] = 'UiAutomator2' #测试框架名称------这一个参数去掉不报错 可以运行
caps['platformName']='Android' #表示的是android 或者IOS系统
caps['platformVersion']='5.1.1' #操作系统的版本
caps['deviceName']='emulator-5554' #虚拟设备号,表示的是设备的ID名称(如果只有一个设备可以用****来替代)
caps['appPackage']='com.bjcsxq.chat.carfriend' #表示的是app的包名
caps['appActivity']='.module_main.activity.SplashActivity' #界面名---可以理解被测程序
#caps['noReset']=True # 用来记住app的session,如果有登陆或做过初始化的操作,为True时,后面不需要再操作
driver=webdriver.Remote('http://127.0.0.1:4723/wd/hub',caps)
driver.implicitly_wait(10)
el = WebDriverWait(driver, 10).until(lambda x: x.find_element_by_xpath("//*[@text='同意并继续使用APP']"))
if el:
#点击同意协议按钮
driver.find_element_by_xpath("//*[@text='同意并继续使用APP']").click()
#点击“我的” ID=com.bjcsxq.chat.carfriend:id/tv_home_mine
driver.find_element_by_id("com.bjcsxq.chat.carfriend:id/tv_home_mine").click()
#点击登录按钮 ID=com.bjcsxq.chat.carfriend:id/mine_username_tv
driver.find_element_by_id("com.bjcsxq.chat.carfriend:id/mine_username_tv").click()
#输入手机号 ID=com.bjcsxq.chat.carfriend:id/login_phone_et
driver.find_element_by_id("com.bjcsxq.chat.carfriend:id/login_phone_et").send_keys("18325539630")
#输入密码 id=com.bjcsxq.chat.carfriend:id/login_pwd_et
driver.find_element_by_id("com.bjcsxq.chat.carfriend:id/login_pwd_et").send_keys("mike123456")
#点击登录 ID=com.bjcsxq.chat.carfriend:id/login_btn
driver.find_element_by_id("com.bjcsxq.chat.carfriend:id/login_btn").click()
#点击确定 按钮 ID=com.bjcsxq.chat.carfriend:id/btn_neg
driver.find_element_by_id("com.bjcsxq.chat.carfriend:id/btn_neg").click()
time.sleep(3)
# 退出驱动
driver.quit()
九、获取手机操作
1、获取手机分辨率
保证脚本在不同机型上都能实现滑屏的操作。
-
driver.get_window_size()
返回的值是字典类型, 包含 height 和 width 高度和宽度的值
2、获取手机截图
-
driver.get_screenshot_as_file(filename)
注意事项:1、路径必须手动创建 2、文件名称必须是以PNG结尾
import time
# 导入webdriver
from appium import webdriver
# 初始化app的配置信息
caps={}
caps['automationName'] = 'UiAutomator2' #测试框架名称------这一个参数去掉不报错 可以运行
caps['platformName']='Android' #表示的是android 或者IOS系统
caps['platformVersion']='5.1.1' #操作系统的版本
caps['deviceName']='emulator-5554' #虚拟设备号,表示的是设备的ID名称(如果只有一个设备可以用****来替代)
caps['appPackage']='com.android.settings' #表示的是app的包名
caps['appActivity']='.Settings' #界面名---可以理解被测程序
driver=webdriver.Remote('http://127.0.0.1:4723/wd/hub',caps)
#获取手机屏幕分辨率
print(driver.get_window_size())
#截图
driver.get_screenshot_as_file("error.png")
time.sleep(2)
driver.quit()
3、获取设置手机网络
主要是为了实现视频类的app中,视频播放过程中网络切换时会有提示信息的操作。
3.1 获取手机网络
-
driver.network_connection
appium定义的网络类型
3.2 设置手机网络
- driver.set_network_connection(connectionType) ----- # connectionType 网络类型的值
import time
# 导入webdriver
from appium import webdriver
# 初始化app的配置信息
caps={}
caps['automationName'] = 'UiAutomator2' #测试框架名称------这一个参数去掉不报错 可以运行
caps['platformName']='Android' #表示的是android 或者IOS系统
caps['platformVersion']='5.1.1' #操作系统的版本
caps['deviceName']='emulator-5554' #虚拟设备号,表示的是设备的ID名称(如果只有一个设备可以用****来替代)
caps['appPackage']='com.android.settings' #表示的是app的包名
caps['appActivity']='.Settings' #界面名---可以理解被测程序
driver=webdriver.Remote('http://127.0.0.1:4723/wd/hub',caps)
#获取网络类型
print(driver.network_connection)
#设置网络类型
driver.set_network_connection(4)
print(driver.network_connection)
time.sleep(2)
driver.quit()
6
4
Process finished with exit code 0
4、模拟键盘操作
常用的三个键值: 3 HOME键, 4 返回键 , 66 回车键
- driver.press_keycode(键值)
5、手机通知栏操作
- driver.open_notififications()
import time
# 导入webdriver
from appium import webdriver
# 初始化app的配置信息
caps={}
caps['automationName'] = 'UiAutomator2' #测试框架名称------这一个参数去掉不报错 可以运行
caps['platformName']='Android' #表示的是android 或者IOS系统
caps['platformVersion']='5.1.1' #操作系统的版本
caps['deviceName']='emulator-5554' #虚拟设备号,表示的是设备的ID名称(如果只有一个设备可以用****来替代)
caps['appPackage']='com.android.settings' #表示的是app的包名
caps['appActivity']='.Settings' #界面名---可以理解被测程序
driver=webdriver.Remote('http://127.0.0.1:4723/wd/hub',caps)
#打开通知栏
driver.open_notifications()
#模拟返回键
driver.press_keycode(4)
time.sleep(2)
driver.quit()
十、滑动和拖拽事件
1、swipe滑动事件
-
driver.swipe(startx, starty, endx, endy, duration=None)
duration用来降低滑屏的速度及惯性, 单位是ms
import time
# 导入webdriver
from appium import webdriver
# 初始化app的配置信息
caps={}
caps['automationName'] = 'UiAutomator2' #测试框架名称------这一个参数去掉不报错 可以运行
caps['platformName']='Android' #表示的是android 或者IOS系统
caps['platformVersion']='5.1.1' #操作系统的版本
caps['deviceName']='emulator-5554' #虚拟设备号,表示的是设备的ID名称(如果只有一个设备可以用****来替代)
caps['appPackage']='com.android.settings' #表示的是app的包名
caps['appActivity']='.Settings' #界面名---可以理解被测程序
driver=webdriver.Remote('http://127.0.0.1:4723/wd/hub',caps)
#滑屏操作
# driver.swipe(216,1635,216,352)
driver.swipe(469,1687,469,252,duration=None)
#定位安全
driver.find_element_by_xpath("//*[@text='安全']").click()
time.sleep(6)
driver.quit()
2、swipe滑动事件封装
- 封装
#封装滑屏操作方法
import time
def execute_swipe(driver,fx,count=1):
#获取屏幕分辨率
w=driver.get_window_size()["width"] #获取手机屏幕的宽度
h=driver.get_window_size()["height"] #获取手机屏幕的高度
if fx == "top": # 往上滑
zb = (w/2, h*0.9, w/2, h*0.1)
elif fx == "down": # 往下滑
zb = (w/2, h*0.1, w/2, h*0.9)
elif fx == 'left': # 往左滑
zb = (w*0.9, h/2, w*0.1, h/2)
else: # 往右滑
zb = (w*0.1, h/2, w*0.9, h/2)
for i in range(count):
driver.swipe(*zb, duration=1200)
time.sleep(1)
- 调用
import time
import q
from demo.q import execute_swipe
# 导入webdriver
from appium import webdriver
# 初始化app的配置信息
from demo.q import execute_swipe
caps={}
caps['automationName'] = 'UiAutomator2' #测试框架名称------这一个参数去掉不报错 可以运行
caps['platformName']='Android' #表示的是android 或者IOS系统
caps['platformVersion']='5.1.1' #操作系统的版本
caps['deviceName']='emulator-5554' #虚拟设备号,表示的是设备的ID名称(如果只有一个设备可以用****来替代)
caps['appPackage']='com.android.settings' #表示的是app的包名
caps['appActivity']='.Settings' #界面名---可以理解被测程序
driver=webdriver.Remote('http://127.0.0.1:4723/wd/hub',caps)
#滑屏操作--调用封装的滑屏函数
#driver.swipe(469,1687,469,252,duration=None)
execute_swipe(driver,"top")
#定位安全
driver.find_element_by_xpath("//*[@text='安全']").click()
time.sleep(6)
driver.quit()
- 案例:要向右滑屏两次,然后点击“立即体验”按钮
#----263apk 打开APP后,要向右滑动两次 才可以点击“立即体验”按钮
import time
import q
from demo.q import execute_swipe
# 导入webdriver
from appium import webdriver
# 初始化app的配置信息
from demo.q import execute_swipe
caps={}
caps['automationName'] = 'UiAutomator2' #测试框架名称------这一个参数去掉不报错 可以运行
caps['platformName']='Android' #表示的是android 或者IOS系统
caps['platformVersion']='5.1.1' #操作系统的版本
caps['deviceName']='emulator-5554' #虚拟设备号,表示的是设备的ID名称(如果只有一个设备可以用****来替代)
caps['appPackage']='com.em.mobile' #表示的是app的包名
caps['appActivity']='.EmProductActivity' #界面名---可以理解被测程序
driver=webdriver.Remote('http://127.0.0.1:4723/wd/hub',caps)
#滑屏操作---要滑屏两次,然后点击“立即体验”按钮
execute_swipe(driver,"left",2)
#点击立即体验按钮
driver.find_element_by_xpath("//*[@text='立即体验']").click()
time.sleep(6)
driver.quit()
3、swipe边滑动边查找封装
针对频道类的元素进行滑动选择对应的频道。
- 封装:
## 封装一个边滑动边查找的方法
def swipe_find(driver, element, element_info):
'''
:param driver: APP驱动对象
:param element: 需要滑动的区域元素对象
:param element_info: 需要找到的元素对象
:return:
'''
ele_size = element.size # 获取元素大小
width = ele_size["width"] # 获取元素的宽度
height = ele_size["height"] # 获取元素的高度
# 获了element元素左上角点的坐标
ele_position = element.location
x = ele_position["x"] # 获取左上角点的x坐标值
y = ele_position["y"] # 获取左上角点的y坐标值
start_x = x+ width*0.9 # 获取的是起始点X的值
y = y + height*0.5 # 获取的是起始及终止点的Y的值
end_x = x + width*0.1 # 获取的是终止点X的值
while True:
# 记录查找前的页面资源, 通过对比页面资源来退出死循环
page = driver.page_source
try:
# 如果有找到对应的元素那么点击并返回
driver.find_element(*element_info).click()
return True
except Exception as e:
print("没有找到该元素!")
# 没有找到元素,那么滑屏后再对比并重新查找
driver.swipe(start_x, y, end_x, y,duration=1000)
time.sleep(1)
if page == driver.page_source:
print("滑屏操作完成且没有找到元素信息")
return False
- 调用
#网易APP
import time
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from demo.q import swipe_find
from appium import webdriver
# 初始化app的配置信息
caps={}
caps['automationName'] = 'UiAutomator2' #测试框架名称------这一个参数去掉不报错 可以运行
caps['platformName']='Android' #表示的是android 或者IOS系统
caps['platformVersion']='5.1.1' #操作系统的版本
caps['deviceName']='emulator-5554' #虚拟设备号,表示的是设备的ID名称(如果只有一个设备可以用****来替代)
caps['appPackage']='com.netease.newsreader.activity' #表示的是app的包名
caps['appActivity']='com.netease.nr.phone.main.MainActivity' #界面名---可以理解被测程序
caps['noReset']=True
driver=webdriver.Remote('http://127.0.0.1:4723/wd/hub',caps)
#找到滑屏的元素 id=com.netease.newsreader.activity:id/bn9
a=WebDriverWait(driver,10,1).until(lambda x:x.find_element_by_id("com.netease.newsreader.activity:id/bn9"))
#定位 房产 频道
b=By.XPATH,"//*[@text='房产']"
#b=driver.find_element_by_xpath("//*[@text='房产']")
#调用封装的变查找边滑屏方法来找 房产 频道
swipe_find(driver,a,b)
time.sleep(6)
driver.quit()
- 结果
4、scroll滑动事件
scroll是通过元素来进行滑动的
- driver.scroll(source_element, target_element)
scroll无法设置滑动的持续时间,带有一定惯性。 主要用于IOS中,android高版本系统可以使用。
#通过scroll来进行滑动操作--从存储 滑到 蓝牙
import time
from demo.q import execute_swipe
from appium import webdriver
# 初始化app的配置信息
from demo.q import execute_swipe
caps={}
caps['automationName'] = 'UiAutomator2' #测试框架名称------这一个参数去掉不报错 可以运行
caps['platformName']='Android' #表示的是android 或者IOS系统
caps['platformVersion']='5.1.1' #操作系统的版本
caps['deviceName']='emulator-5554' #虚拟设备号,表示的是设备的ID名称(如果只有一个设备可以用****来替代)
caps['appPackage']='com.android.settings' #表示的是app的包名
caps['appActivity']='.Settings' #界面名---可以理解被测程序
driver=webdriver.Remote('http://127.0.0.1:4723/wd/hub',caps)
# 存储 按钮
cz=driver.find_element_by_xpath("//*[@text='存储']")
# 蓝牙 按钮
lanya=driver.find_element_by_xpath("//*[@text='蓝牙']")
#通过scroll来进行滑动操作
driver.scroll(cz,lanya)
time.sleep(6)
driver.quit()
5、drag_and_drop拖拽事件
从一个元素滑动到另外一个元素的位置, 同时也能实现将一个元素拖动另一个元素当中。
- driver.drag_and_drop(source_element, target_element)
- source_element 表示的是被拖动的元素对象
- target_element 表示的是目标元素对象
#通过拖动来实现滑屏操作-----从更多 按钮 滑到# 存储 按钮
import time
from appium import webdriver
# 初始化app的配置信息
caps={}
caps['automationName'] = 'UiAutomator2' #测试框架名称------这一个参数去掉不报错 可以运行
caps['platformName']='Android' #表示的是android 或者IOS系统
caps['platformVersion']='5.1.1' #操作系统的版本
caps['deviceName']='emulator-5554' #虚拟设备号,表示的是设备的ID名称(如果只有一个设备可以用****来替代)
caps['appPackage']='com.android.settings' #表示的是app的包名
caps['appActivity']='.Settings' #界面名---可以理解被测程序
driver=webdriver.Remote('http://127.0.0.1:4723/wd/hub',caps)
# 存储 按钮
cz=driver.find_element_by_xpath("//*[@text='存储']")
# 更多 按钮
gengduo=driver.find_element_by_xpath("//*[@text='更多']")
#通过拖动来实现滑屏操作
driver.drag_and_drop(cz,gengduo)
time.sleep(6)
driver.quit()
十一、高级手势操作
实现步骤:
1、创建TouchAction对象
2、调用手势方法
3、调用perform() 执行操作
1、轻敲操作
实现步骤:
-
action = TouchAction(driver) # 创建建手势对象
-
action.tap(element=None, x=None, y=None, count=1)
- 调用轻敲手势方法,传入的是一个元素对象或者是一个坐标点 count表示的是轻敲的次数, 默认值为1.
-
action.perform() # 调用perform()执行轻敲操作
如果是轻敲一次的话count=1,效果和click()事件效果一样
示例:元素对象轻敲
import time
from appium import webdriver
from appium.webdriver.common.touch_action import TouchAction
# 初始化app的配置信息
caps={}
caps['automationName'] = 'UiAutomator2' #测试框架名称------这一个参数去掉不报错 可以运行
caps['platformName']='Android' #表示的是android 或者IOS系统
caps['platformVersion']='5.1.1' #操作系统的版本
caps['deviceName']='emulator-5554' #虚拟设备号,表示的是设备的ID名称(如果只有一个设备可以用****来替代)
caps['appPackage']='com.android.settings' #表示的是app的包名
caps['appActivity']='.Settings' #界面名---可以理解被测程序
driver=webdriver.Remote('http://127.0.0.1:4723/wd/hub',caps)
# WLAN 按钮
cz=driver.find_element_by_xpath("//*[@text='WLAN']")
# 调用轻敲手势操作
#1.创建手势对象
action=TouchAction(driver)
#2.调用手势方法
action.tap(cz, count=1)
#3.调用执行方法
action.perform()
time.sleep(3)
driver.quit()
示例:改成坐标,不用元素定位对象了(285 492)
import time
from appium import webdriver
from appium.webdriver.common.touch_action import TouchAction
# 初始化app的配置信息
caps={}
caps['automationName'] = 'UiAutomator2' #测试框架名称------这一个参数去掉不报错 可以运行
caps['platformName']='Android' #表示的是android 或者IOS系统
caps['platformVersion']='5.1.1' #操作系统的版本
caps['deviceName']='emulator-5554' #虚拟设备号,表示的是设备的ID名称(如果只有一个设备可以用****来替代)
caps['appPackage']='com.android.settings' #表示的是app的包名
caps['appActivity']='.Settings' #界面名---可以理解被测程序
driver=webdriver.Remote('http://127.0.0.1:4723/wd/hub',caps)
# 调用轻敲手势操作
#1.创建手势对象
action=TouchAction(driver)
#2.调用手势方法
action.tap(x=285,y=492, count=1)
#3.调用执行方法
action.perform()
time.sleep(3)
driver.quit()
2、按下和抬起操作
按下:
press(element, x, y)
抬起:
release()
- TouchAction(driver).press(x=477, y=489).release().perform()
按下和抬起可以结合起来使用,达到点击的效果
import time
from appium import webdriver
from appium.webdriver.common.touch_action import TouchAction
# 初始化app的配置信息
caps={}
caps['automationName'] = 'UiAutomator2' #测试框架名称------这一个参数去掉不报错 可以运行
caps['platformName']='Android' #表示的是android 或者IOS系统
caps['platformVersion']='5.1.1' #操作系统的版本
caps['deviceName']='emulator-5554' #虚拟设备号,表示的是设备的ID名称(如果只有一个设备可以用****来替代)
caps['appPackage']='com.android.settings' #表示的是app的包名
caps['appActivity']='.Settings' #界面名---可以理解被测程序
driver=webdriver.Remote('http://127.0.0.1:4723/wd/hub',caps)
# WLAN 按钮
WLAN=driver.find_element_by_xpath("//*[@text='WLAN']")
# 调用按下手势操作
TouchAction(driver).press(WLAN).perform()
# 等待2S
time.sleep(2)
TouchAction(driver).press(WLAN).release().perform()
time.sleep(3)
driver.quit()
3 、等待操作【掌握】
模拟手指等待。 wait(ms=0) ms表示的是毫秒数
- TouchAction(driver).press(x=650,y=650).wait(5000).release().perform()
示例:进入WLAN页面,对WiFi名称进行长按 会弹出弹框
import time
from appium import webdriver
from appium.webdriver.common.touch_action import TouchAction
# 初始化app的配置信息
caps={}
caps['automationName'] = 'UiAutomator2' #测试框架名称------这一个参数去掉不报错 可以运行
caps['platformName']='Android' #表示的是android 或者IOS系统
caps['platformVersion']='5.1.1' #操作系统的版本
caps['deviceName']='emulator-5554' #虚拟设备号,表示的是设备的ID名称(如果只有一个设备可以用****来替代)
caps['appPackage']='com.android.settings' #表示的是app的包名
caps['appActivity']='.Settings' #界面名---可以理解被测程序
driver=webdriver.Remote('http://127.0.0.1:4723/wd/hub',caps)
# 找到 WLAN 按钮
driver.find_element_by_xpath("//*[@text='WLAN']").click()
time.sleep(2)
#通过登录级按下和抬起---实现对WiFi名称进行长按
TouchAction(driver).press(x=512,y=483).wait(3000).release().perform()
time.sleep(3)
driver.quit()
4、长按操作
-
long_press(element, x=None, y=None, duration=1000)
element表示的是元素对象
x, y表示的是坐标点
duration 表示的是长按的时长,单位是毫秒
TouchAction(driver).long_press(x=650, y=650,duration=2000).perform()
import time
from appium import webdriver
from appium.webdriver.common.touch_action import TouchAction
# 初始化app的配置信息
caps={}
caps['automationName'] = 'UiAutomator2' #测试框架名称------这一个参数去掉不报错 可以运行
caps['platformName']='Android' #表示的是android 或者IOS系统
caps['platformVersion']='5.1.1' #操作系统的版本
caps['deviceName']='emulator-5554' #虚拟设备号,表示的是设备的ID名称(如果只有一个设备可以用****来替代)
caps['appPackage']='com.android.settings' #表示的是app的包名
caps['appActivity']='.Settings' #界面名---可以理解被测程序
driver=webdriver.Remote('http://127.0.0.1:4723/wd/hub',caps)
# 找到 WLAN 按钮
driver.find_element_by_xpath("//*[@text='WLAN']").click()
time.sleep(2)
#通过登录级按下和抬起---实现对WiFi名称进行长按
#TouchAction(driver).press(x=512,y=483).wait(3000).release().perform()
#第二种长按方法:
TouchAction(driver).long_press(x=512,y=483,duration=3000).perform()
time.sleep(3)
driver.quit()
5、移动操作(如手势解锁)
模拟手指在手机屏幕上移动的过程
- move_to(element, x=x, y=y) ele表示的是元素对象, x和y表示的是坐标点。二选其一。
移动的操作是需要结合press和release一起使用。
import time
from appium import webdriver
from appium.webdriver.common.touch_action import TouchAction
# 初始化app的配置信息
caps={}
caps['automationName'] = 'UiAutomator2' #测试框架名称------这一个参数去掉不报错 可以运行
caps['platformName']='Android' #表示的是android 或者IOS系统
caps['platformVersion']='5.1.1' #操作系统的版本
caps['deviceName']='emulator-5554' #虚拟设备号,表示的是设备的ID名称(如果只有一个设备可以用****来替代)
caps['appPackage']='com.android.settings' #表示的是app的包名
caps['appActivity']='.Settings' #界面名---可以理解被测程序
driver=webdriver.Remote('http://127.0.0.1:4723/wd/hub',caps)
driver.find_element_by_xpath("//*[@text='我的']").click()
TouchAction(driver).press(x=260, y=720).wait(500).move_to(x=540, y=720).wait(500)\
.move_to(x=820,y=720).wait(500).move_to(x=540, y=1000).wait(500).move_to(x=260, y=1270)\
.wait(500).move_to(x=540, y=1270).wait(500).move_to(x=820, y=1270).release().perform()
time.sleep(5)
driver.quit()
十二、toast操作
技术1:用到封装显示等待方法
技术2:用到封装判断元素是否存在
1.获取toast消息
获取toast消息,在初始化配置中需要增加一个配置项。否则定位不到。
- "automationName": "Uiautomator2"
示例:进入设置页面, 点击“关于平板电脑” 点击版本号 获取toast信息
- 用到之前封装的方法
def get_element(driver, element): # element 表示的元素定位的值
wait = WebDriverWait(driver, 10, 1)
element = wait.until(lambda x: x.find_element(element[0], element[1]))
return element
# 判断元素是否存
def element_is_exsit(driver, element): # element 表示的元素定位的值
try: # 捕获异常信息
get_element(driver, element) # 能够正常找元素,就返回True
return True
except Exception as e: # 如果捕获到了异常,返回False
return False
- toast代码
import time
from appium import webdriver
from selenium.webdriver.common.by import By
from demo.q import execute_swipe, element_is_exsit, get_element
# 初始化app的配置信息
caps={}
caps['automationName'] = 'Uiautomator2' #测试框架名称------这一个参数去掉不报错 可以运行 toast消息定位需要这个参数
caps['platformName']='Android' #表示的是android 或者IOS系统
caps['platformVersion']='5.1.1' #操作系统的版本
caps['deviceName']='emulator-5554' #虚拟设备号,表示的是设备的ID名称(如果只有一个设备可以用****来替代)
caps['appPackage']='com.android.settings' #表示的是app的包名
caps['appActivity']='.Settings' #界面名---可以理解被测程序
caps['noReset']=True
driver=webdriver.Remote('http://127.0.0.1:4723/wd/hub',caps)
#上划--要滑2-3次 (调用之前封装swipe的方法)
execute_swipe(driver,"top",count=2)
#点击 关于平板电脑
driver.find_element_by_xpath("//*[@text='关于平板电脑']").click()
#上划1次
time.sleep(2)
execute_swipe(driver,"top",count=1)
#点击 版本号 --轻敲3次
driver.find_element_by_xpath("//*[@text='版本号']").click()
time.sleep(1)
driver.find_element_by_xpath("//*[@text='版本号']").click()
time.sleep(1)
driver.find_element_by_xpath("//*[@text='版本号']").click()
time.sleep(1)
#获取toast消息
toast_btn = By.XPATH, "//*[contains(@text, '开发者模式')]"
# driver.find_element(*toast_btn).click()
if element_is_exsit(driver, toast_btn):
print("能够定位到toast消息:{}".format(get_element(driver,toast_btn).text))
else:
print("不能定位到toast消息")
time.sleep(3)
driver.quit()
- 结果
能够定位到toast消息:只需 4 步操作即可进入开发者模式。
Process finished with exit code 0
2.封装获取toast消息方法
- 封装
#定义获取toast消息方法
def get_toast(driver,message,timeout=3):
# 通过{} 符号将message当参数传到xpath表达式中去
xapth="//*[contains(@text,'{}')]".format(message)
#或者直接写 如:
#xpath = F"//*[contains(@text, '" + message +"')]"
wait=WebDriverWait(driver,timeout,1)
element=wait.until(lambda x: x.find_element(By.XPATH,xapth))
return element.text
- 调用
import time
from appium import webdriver
from demo.q import execute_swipe, get_toast
# 初始化app的配置信息
caps={}
caps['automationName'] = 'Uiautomator2' #测试框架名称------这一个参数去掉不报错 可以运行 toast消息定位需要这个参数
caps['platformName']='Android' #表示的是android 或者IOS系统
caps['platformVersion']='5.1.1' #操作系统的版本
caps['deviceName']='emulator-5554' #虚拟设备号,表示的是设备的ID名称(如果只有一个设备可以用****来替代)
caps['appPackage']='com.android.settings' #表示的是app的包名
caps['appActivity']='.Settings' #界面名---可以理解被测程序
caps['noReset']=True
driver=webdriver.Remote('http://127.0.0.1:4723/wd/hub',caps)
#上划--要滑2-3次 (调用之前封装swipe的方法)
execute_swipe(driver,"top",count=2)
#点击 关于平板电脑
driver.find_element_by_xpath("//*[@text='关于平板电脑']").click()
#上划1次
time.sleep(2)
execute_swipe(driver,"top",count=1)
#点击 版本号 --轻敲3次
driver.find_element_by_xpath("//*[@text='版本号']").click()
time.sleep(1)
driver.find_element_by_xpath("//*[@text='版本号']").click()
time.sleep(1)
driver.find_element_by_xpath("//*[@text='版本号']").click()
time.sleep(1)
#获取toast消息
message="开发者模式"
print(get_toast(driver,message))
time.sleep(3)
driver.quit()
只需 4 步操作即可进入开发者模式。
Process finished with exit code 0
十三、webview操作(H5)
1.环境安装:
1、需要查看手机或者模拟器上webView的版本 (webView的版本必须要与chromedriver的版本配套)
- 可以下载2.23的驱动版本,支持52的版本
2、在手机或者模拟器上面安装chrome浏览器(手机或者模拟器中chrome版本要低于电脑上chrome的版本)
3、设置PC电脑上面的appium中chromedriver的版本,chrome版本要与webView的版本配套。
-
替找appium中的chrome版本:
-
C:\Program Files (x86)\Appium\resources\app\node_modules\appium\node_modules\appiumchromedriver\chromedriver\win
-
刚刚下载的2.23版本的谷歌浏览器驱动,去替换掉这个目录下的驱动
-
2.查看H5页面的元素信息
1、在手机或者模拟器当中打开H5的页面
2、在PC的chrome浏览器当中,打开对应的地址:chrome://inspect/#devices
- 要FQ,不然点击inspect 可能打开的devtools空白
3、通过devtools来查看对应的元素信息。
3.代码实现步骤:
1、首先要获取context的信息, 如果是原生的app,context的信息显示为Native App, 如果页面为webView的页面,context的信息
显示为webView的名称。如果需要在app当中查看对应的webView的名,需要在app的代码当中加上以下的代码:
if
(Build.VERSION.SDK_INT>=Build.VERSION_CODES.KITKAT)
{
WebView.setWebContentsDebuggingEnabled(true);
}
2、切换到web页面
driver.switch_to.context(context)
案例:模拟器打开浏览器,输入百度,搜索“python "点击搜索按钮
import time
from appium import webdriver
# 初始化app的配置信息
caps={}
caps['automationName'] = 'Uiautomator2' #测试框架名称------这一个参数去掉不报错 可以运行 toast消息定位需要这个参数
caps['platformName']='Android' #表示的是android 或者IOS系统
caps['platformVersion']='5.1.1' #操作系统的版本
caps['deviceName']='emulator-5554' #虚拟设备号,表示的是设备的ID名称(如果只有一个设备可以用****来替代)
caps['appPackage']='com.android.browser' #表示的是app的包名
caps['appActivity']='.BrowserActivity' #界面名---可以理解被测程序
caps['noReset']=True
#caps['chromedriverExecutableDir']=r"D:\BaiduNetdiskDownload\apptools\apk\chromedriver_win32_2.22"
# 用来指定chrome驱动的目录 报找不到驱动文件就加上这个参数,
driver=webdriver.Remote('http://127.0.0.1:4723/wd/hub',caps)
print(driver.contexts)
#结果:----['NATIVE_APP', 'WEBVIEW_com.android.browser']
driver.get("http://m.baidu.com")
driver.switch_to.context('WEBVIEW_com.android.browser')
time.sleep(2)
driver.find_element_by_id("index-kw").send_keys("python")
time.sleep(3)
driver.find_element_by_id("index-bn").click()
time.sleep(6)
driver.quit()
4,在APP中点击按钮切换到h5页面
def test_h5qy(self):
#点击我的 按钮
time.sleep(2)
self.driver.find_elements_by_id("com.youdao.note:id/tab_name")[3].click()
#滚屏操作(向下滚动)
time.sleep(2)
self.driver.swipe(90,1800,90,890)
#点击有道云企业版按钮
time.sleep(2)
self.driver.find_element_by_id("com.youdao.note:id/youdao_corp_enterprise").click()
#切换到h5
#获取相关的页面的标识
time.sleep(5)
page=self.driver.contexts
print(page)
time.sleep(2)
self.driver.switch_to.context('WEBVIEW_com.youdao.note')
#self.driver.switch_to.context(page[1])
#所有的自动化测试转入web端
time.sleep(2)
self.driver.find_element_by_css_selector(".to-group.top-btn").click()
#self.driver.find_element_by_class_name(".qq.btn").click()
#点击手机退回键
time.sleep(2)
self.driver.press_keycode("4")
#切换到手机APP模式下
self.driver.switch_to.context("NATIVE_APP")
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?