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、兼容性测试 (专项)

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的元素信息。

    查看元素信息:

    image-20220809163302316

示例:先报存当前页面的元素信息,(如保存到桌面),然后在打开文件 就可以实现在代码运行中去查看定位了

image-20220809200826194
  • 如果出现如下错误:

    image-20220809163321796

需要重启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']")

    单个元素定位不到会报错。

示例:

image-20220809203711039
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的值)

示例:

image-20220809220348189
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名称进行长按 会弹出弹框

image-20220811165555001
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")
posted @   mike002  阅读(923)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
点击右上角即可分享
微信分享提示