15 移动端app自动化测试 - 软件测试

2023-11-14

软件测试所有内容笔记正在陆续更新中,笔记已经在本地记录,全部为自己手动记录的笔记及总结,正在开始更新中,后续会逐步更新并完善到 软件测试学习内容总结 专栏。
本节内容:移动端app自动化测试

文章目录

1. appium环境安装与架构介绍


1.1 目前mobile自动化解决方案

自动化工具选择

  • 单平台测试 or 多平台测试?
  • 是否有多设备同时测试的场景?
  • 不局限于测试环境,任何版本任何环境都可以测试?
  • 最擅长哪种开发语言?
  • 当前市面是否有满足项目需求的测试工具?是否需要二次开发?

1.2 appium 介绍

Appium是一个移动端的自动化测试框架,可用于测试原生应用,移动网页应用和混合应用,且是跨平台。可用于iOS和Android操作系统。原生应用是指用Android或iOS编写的应用,移动网页应用是指网页应用,类似于iOS中Safari应用或者Chrome应用或者类似浏览器的应用。混合应用是指一种包裹webview的应用,原生应用网页内容交互性的应用。

重要的是Appium是跨平台的。何为跨平台,意思是可以针对不同平台用一套api来表写脚本。

原生应用 – 手机设置,
移动网页应用 – 手机浏览器打开的应用,
混合应用 – 原生应用嵌套了网页应用,微信小程序


推荐Appium

  • 跨语言:Java、Python、nodejs等
  • 跨平台
    • Android、iOS
    • Windows、Mac
  • 底层多引擎可切换
  • 生态丰富、社区强大

Appium工作引擎

对于Android、iOS底层使用了不同的工作引擎驱动实现自动化测试。Appium引擎列表:
在这里插入图片描述

Appium的设计理念

  • webdriver是基于http协议的,第一连接会建立一个session会话,并通过post发送一个json告知服务端相关测试信息
  • Client/Server设计模式
    • 客户端通过WebDriver json wire协议与服务端通讯
    • 多语言支持
  • Server可以放在任何地方
  • 服务端NODEJS开发的HTTP服务
  • appium使用appium-xcuitest-driver来测试iPhone设备,其中需要安装Facebook出的WDA(webdriver agent)来驱动iOS测试

在这里插入图片描述

入门篇 - appium环境安装

appium生态工具

  • adb:Android的控制工具,用于获取Android的各种数据和控制
  • Appium Desktop:内嵌了Appium server和inspector的综合工具
  • Appium Server:Appium的核心工具,命令行工具
  • Appium client:各种语言的客户端封装库,用于连接Appium server
    • Python、Java、ruby、robotframework-appium
  • AppCrawler:自动化遍历工具 --思寒

Appium安装 - 简化版

环境安装

  • Java 1.8版本(配置环境变量)
  • Android SDK(配置环境变量)
  • Appium Desktop
  • Python3
  • Appium python client

软件下载地址

JDK安装与配置

SDK安装与配置 - 简化版

  • 第一种方式:

  • 安装sdk

  • 配置android SDK环境变量:(注意:路径不要有特殊符号,不要有空格,不要有中文,使用正常格式的英文路径即可)

    • ANDROID_HOME           D:\adt-bundle-mac-x86_64-20140702\sdk
    • PATH                 %ANDROID_HOME%\tools;%ANDROID_HOME%\platform-tools
  • 检查是否安装成功,cmd输出

    • adb回车或者adb shell 然后回车
  • 更新sdk
    tools\android.bat update sdk --no-ui
    在这里插入图片描述


SDK安装与配置 - 进阶版

Appium Desktop 安装与配置

Appium 客户端安装与配置

  • 安装Python3环境
    • <topic/57> 安装Python+pycharm环境帖
  • 安装Appium python client两种方式:

运行测试用例

  • 验证环境是否成功
    • 1、首先打开appium desktop,点击start server(不报错)
    • 2、其次准备一个Android设备,真机或者模拟器(推荐mumu模拟器)
    • 3、模拟器连接电脑
    • 4、adb devices查看设备是否连接
    • 5、最后编写测试脚本,运行脚本,不报错

下载安装模拟器

  • mumu模拟器
  • 电脑开启VT(虚拟化技术)
  • 设置屏幕显示(720*1280)重启
  • 连接设备adb connect

代码示例

  • 下面代码论坛帖地址:
    • <topic/12652>

Appium安装 - 服务版

Appium Server环境信赖

  • Java1.8版本
  • Android sdk
  • Node js(>=10版本),npm(>=6版本)(推荐下载Node.js 12.x)(重点)
  • Appium Server
  • Python3
  • Appium python client

Node.js安装

  • Node.js 下载地址:
  • https://nodejs.org/en/download/releases/
  • 推荐下载Node.js版本12.x(Windows:msi文件,Mac:pkg)
  • 安装之后会自带一个工具npm,可以使用这个工具安装Appium server
  • 无需配置环境变量(安装完成重启命令提示行cmd)

安装 Appium Server

  • 如果不需要Appium inspector,也可以通过npm直接安装Appium server
  • 官方安装(推荐)
    • npm install -g appium (-g参数表示全局安装)(不建议这样 安装,这样安装最新版)
    • npm install -g appium@1.91.1 指定版本安装(最新1.21,建议安装低1-2个版本)
  • 淘宝提供(不推荐)
    • npm install -g cnpm --registry.npm.taobao.org
    • cnpm install -g appium
  • 运行
    • appium --version 查看版本
    • appium 启动Appium服务(不报错说明安装成功)

Appium Doctor安装

  • 安装appium-doctor检测appium的安装环境
    • npm install -g appium-doctor
  • 在命令行执行appium-doctor

在这里插入图片描述

运行测试用例

  • 验证环境是否成功
    • 1、首先运行appium server(不报错)
    • 2、其次准备一个Android设备,真机或者模拟器(推荐mumu模拟器)
    • 3、模拟器连接电脑
    • 4、adb devices查看设备是否连接
    • 5、最后编写测试脚本,运行脚本,不报错

启动appium server
创建文件demo.py,执行python demo.py

from appium import webdriver 
desired_caps={} 
desired_caps['platformName']='Android' 
desired_caps['platformVersion']='6.0' 
desired_caps['deviceName']='emulator-5554' 
# com.android.settings/com.android.settings.Settings
desired_caps['appPackage']='com.android.settings' 
desired_caps['appActivity']='com.android.settings.Settings' 

driver=webdriver.Remote('http://localhost:4723/wd/hub',desired_caps) 
print("启动【设置】应用") 
driver.quit()

1.3 appium 框架介绍

1.4 appium 环境安装


2. appium用例录制

2.1 android自动化前提依赖

Android自动化前提依赖

  • adb工具
  • 模拟器 or 真机
    • 模拟器:网易mumu,genimotion,或者SDK自带的模拟器
    • 真机需要root权限
  • Appium Desktop:入门学习工具

2.2 appium desktop功能介绍

desktop主要功能

  • UI分析
  • 录制用例
  • 元素查找测试
  • Attach已有的session
  • 云测试

2.3 利用appium desktop生成用例模板

获取app的信息

  • app信息
    • 获取当前界面元素:adb shell dumpsys activity top(推荐)(重点)
    • 获取任务列表:adb shell dumpsys activity activities
  • app入口
    • adb logcat | grep -i displayed(推荐)(重点)
    • aapt dump badging mobike.apk | grep launchable-activity
    • apkanalyzer 最新版本的sdk中才有
  • 启动应用
    • adb shell am start -W -n com.xueqiu.android/.view/WelcomeActivityAlias -S(重点)

adb shell dumpsys activity top 查找最上层的activity的展示
adb shell am start -W -n com.xueqiu.android/.main.view.MainActivity

配置待测应用的信息(desire capability)

导出python语言的用例

添加隐式等待增强用例稳定性

配置待测应用
利用Appium Desktop生成用例模板
在这里插入图片描述


在这里插入图片描述


: start inspector session: get raw logs - 下载日志到本地: stop server


Automatic Server:自动的server
Custom Server:本地的server
Select Cloud Providers:云服务 - 国外

在这里插入图片描述

https://github.com/appium/appium/blob/master/docs/en/writing-running-appium/caps.md

{
“platformName”: “android”,
“deviceName”: “mumu”,
“appPackage”: “com.xueqiu.android”,
“appActivity”: “.view.WelcomeActivityAlias”
}

在这里插入图片描述

按钮1 - 选择页面元素,会在右边的布局结构中展示元素的位置及层级结构,在最右侧展示出元素的所有的属性
2 - 滑动 通过坐标点进行滑动(给定2个坐标点-鼠标在页面不同位置点击)
3 - 点击 通过坐标点进行点击
4 - 返回
5 - 刷新
6 - 录制脚本
7 - 搜索
8 - 拷贝 拷贝当前xml的结构
9 - 关闭session

在这里插入图片描述

el2 = driver.find_element_by_xpath("/hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.view.ViewGroup/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.RelativeLayout/android.view.ViewGroup/android.widget.LinearLayout/android.widget.RelativeLayout[1]/android.widget.RelativeLayout/android.widget.ViewFlipper/android.widget.LinearLayout/android.widget.TextView")
el2.click()
el3 = driver.find_element_by_id("com.xueqiu.android:id/search_input_text")
el3.send_keys("alibaba")
el4 = driver.find_element_by_xpath("/hierarchy/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.view.ViewGroup/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.RelativeLayout/android.widget.FrameLayout/android.widget.LinearLayout/androidx.recyclerview.widget.RecyclerView/android.widget.RelativeLayout[1]/android.widget.LinearLayout/android.widget.TextView[1]")
el4.click()


3. 元素定位方法与隐式等待

3.1 desirecapability介绍

测试用例的重要部分

  • 导入依赖:
    • from appium import webdriver
  • capabilities 设置
  • 初始化driver:
    • python webdriver.remote
  • 隐式等待,增强用例的稳定性
  • 元素定位与操作 find+action
  • 断言 assert

Capability设置

  • app apk地址
  • appPackage 包名
  • appActivity Activity名字
  • automationName 默认使用uiautomator2(android默认使用uiautomator2,iOS默认使用XCUITest)
  • noReset fullReset 是否在测试前后重置相关环境(例如首次打开弹框,或者是登录信息)
    • 演示雪球的首次启动弹窗功能,noreset = True, noreset = false情况
  • unicodeKeyBoard resetKeyBoard 是否需要输入非英文之外的语言并在测试完成后重置输入法
    • 举例输入中文,alibaba,阿里巴巴
  • 官方文档:https://github.com/appium/appium/blob/master/docs/en/writing-running-appium/caps.md
  • dontStopAppOnReset 首次启动的时候,不停止app(可以调试或者运行的时候提升运行速度)
  • skipDeviceInitialization 跳过安装,权限设置等操作(可以调试或者运行的时候提升运行速度)

3.2 appium元素定位

appium元素定位

  • 常用的两种定位方式id,accessibility_id
    • driver.find_element_by_id(resource-id)
    • driver.find_element_by_accessibility(content-desc)

三种经典等待方式

  • 强制等待
    • sleep 不推荐
  • 隐式等待(全局性)
    • 设置一个超时时间,服务端appium会在给定的时间内,不停的查找,默认值是0
    • 用法:driver.manage().timeouts().implicitlyWait(10,TimeUnit.SECONDS);
    • 在服务端等待
  • 显示等待(等待某个元素)
    • Element = WebDriverWait(driver,10,0.5).until(\ expected_conditions.visibility_of_element_located((MobileBy.ID,"com.android.settings:id/title")))
    • 在客户端等待

3.3 隐式等待

隐式等待

  • 使用方法
    • driver.implicitly_wait(time) -全局的等待

实例展示

from appium import webdriver

desired_caps={}
desired_caps['platformName'] = 'Android'
desired_caps[''] = ''
desired_caps['noReset'] = 'true'

driver = webdriver.Remote('http://12.0.0.1:4723/wd/hub', desired_caps)
driver.implicitly_wait(5)

driver.quit()

在这里插入图片描述

driver = webdriver.Remote(‘http://12.0.0.1:4723/wd/hub’, desired_caps)
driver.implicitly_wait(5) -全局的等待

4. app控件定位

4.1 android/ios基础知识

Android基础知识

  • Android是通过容器的布局属性来管理子控件的位置关系,布局过程就是把界面上的所有的控件 根据他们的间距的大小,摆放在正确的位置

  • Android七大布局

    • LinearLayout(线性布局)
    • RelativeLayout(相对布局)
    • FrameLayout(帧布局)
    • AbsoluteLayout(绝对布局)
    • TableLayout(表格布局)
    • GridLayout(网格布局)
    • ConstraintLayout(约束布局)
      在这里插入图片描述
  • Android四大组件

    • activity         与用户交互的可视化界面
    • service         实现程序后台运行的解决方案
    • content provider       内容提供者,提供程序所需要的数据
    • broadcast receiver     广播接收器,监听外部事件的到来(比如来电)
       
  • 常用的控件

    • TextView(文本控件),EditText(可编辑文本控件)
    • Button(按钮),ImageButton(图片按钮),ToggleButton(开关按钮)
    • ImageView(图片控件)
    • CheckBox(复选框控件),RadioButton(单选框控件)

  • 布局是一种可用于放置很多控件的容器,它可以按照一定的规律调整内部控件的位置,从而编写出精美的界面。当然,布局的内部除了放置控件外,也可以放置布局,通过多层布局的嵌套,我们就能够完成一些比较复杂的界面。
    在这里插入图片描述

iOS基础知识

  • iOS介绍
    • 由苹果公司为iPhone开发的操作系统,主要给iPhone,iTouch,iPad使用
    • 原名iPhoneOS,2010年WWDC大户改名为iOS
    • 目前iOS最新版本是iOS13
  • 布局
    • iOS去掉了布局的概念,直接用变量之间的相对关系完成位置的计算
  • 开发环境
    • 系统:MacOS X
    • 开发工具:Xcode
    • 开发语言:ObjectC
    • 安装文件:.ipa文件 / .app文件
  • 注意:
    • 使用Appium测试iOS应用需要使用MacOS操作系统

元素定位

  • 元素定位,实际上就是定位控件
  • 要想一个脚本同时支持android/iOS两个系统,就得保证元素属性(id,aid,xpath)一致

控件基础知识

  • dom:Document Object Model 文档对象模型
  • dom应用:最早应用于html和js的交互。用于表示界面的控件层级,界面的结构化描述,常见的格式为html、xml。核心元素为节点和属性。
  • xpath:xml路径语言,用于xml中的节点定位。
    在这里插入图片描述
  • Android应用的层级结构与html不一样,是一个定制的xml
  • app source类似于dom,表示app的层级,代表了界面里面所有的控件树的结构
  • 每个控件都有它的属性(resourceid,xpath,aid),没有css属性
    在这里插入图片描述

4.2 dom结构解读

app dom结构解析
在这里插入图片描述

app dom为例

  • node
  • attribute
    • clickable
    • content-desc
    • resource-id
    • text
    • bounds
  • iOS与Android的区别
    • dom属性和节点结构类似
    • 名字和属性的命名不同(比如:android resourceid,ios name;android content-des,ios accessibility-id)

在这里插入图片描述

4.3 id、aid、xpath定位方法

定位方法

  • 测试步骤三要素:
    • 定位、交互、断言
  • 定位方法:
    • id定位
      • driver.find_element_by_id(resource-id属性值)
      • driver.find_element(MobileBy.ID,“resource:id”)
    • accessibility_id定位
      • driver.find_element_by_accessibility_id(content-desc属性值)
      • driver.find_element(MobileBy.ACCESSIBILITY_ID,“content_desc:属性”)
    • xpath定位
      • driver.find_element_by_xpath(xpath属性值)
    • classname定位(不推荐)
  • https://www.freeformatter.com/xpath-tester.html #ad-output格式化xml

4.4 uiautomatorviewer定位工具使用

定位工具

  • uiautomatorviewer工具(only android)
    • 推荐使用
    • sdk路径下的工具
    • Appium inspector工具

实战演示

  • 打开 雪球 app
  • 想搜索框输入文本 alibaba
  • 获取【阿里巴巴】这只股票的价格
  • 判断股票的价格大于120

5. app控件交互

5.1 元素的常用方法

  • 点击方法 element.click()
  • 输入操作 element.send_keys(“appium”)
  • 设置元素的值 element.set_value(“appium”)
  • 清除操作 element…clear()
  • 是否可见 element.is_displayed() 返回 True/False
  • 是否可用 element.is_enabled() 返回 True/False
  • 是否被选中 element.is_selected() 返回 True/False
  • 获取属性值 get_attribute(name)

  • get_attribute()方法能获取的属性,元素的属性几乎都能获取到,属性名称和uiautomatorviewer里面的一致
  • 注意:有些属性展示在uiautomatorviewer里,但是不能通过get_attribute获取,比如:index

5.2 元素的常用属性

  • 获取元素文本
    • 格式:element.text
  • 获取元素坐标
    • 格式:element.location
    • 结果:{‘y’: 19, ‘x’: 498}
  • 获取元素尺寸(高和宽)
    • 格式:element.size
    • 结果:{‘width’: 500, ‘height’: 22}

案例

  • 打开 雪球 应用首页
  • 定位首页的搜索框
  • 判断搜索框是否可用,并查看搜索框name属性值
  • 打印搜索框这个元素的左上角坐标和它的宽高
  • 向搜索框输入:alibaba
  • 判断【阿里巴巴】是否可见
  • 如果可见,打印”搜索成功“点击,如果不可见,打印”搜索失败“

6. 触屏操作自动化

TouchAction

点击

滑动

手势操作

  • TouchAction(driver).press(x=244,y=374).wait(100).move_to(x=711,y=374).wait(100).move_to(x=1198,y=374).wait(100).move_to(x=1198,y=865).wait(100).move_to(x=1198,y=1323).wait(100).release().perform()

7. 高级定位技巧

7.1 Xpath定位进阶

  • 层级定位
    • 父节点定位子节点
    • 子节点定位父节点
    • 子节点定位兄弟节点
    • 爷爷节点定位孙子节点

Xpath定位

案例演示

  • 使用通过Appium desktop 来查找兄弟节点
  • 用例
    • 打开【雪球】app
    • 搜索“alibaba”
    • 从搜索结果查找,阿里巴巴[香港股票]的价格

7.2 uiautomator定位表达式

uiautomator定位


  • 通过resource-id定位
  • 通过classname定位
  • 通过content-desc定位
  • 通过文本定位
  • 组合定位
  • 通过父子关系定位

  • 通过resourceid定位
    • new UiSelector().resourceId(“id”)
  • 通过classname定位
    • new UiSelector().className(“className”)
  • 通过content-desc定位
    • new UiSelector().description(“contenet-des属性”)

  • 用法:
    • driver.find_element_by_android_uiautomator(表达式).click()
  • 通过文本定位
    • 通过text文本定位语法
      • new UiSelector().text("text文本")
    • 如果文本比较长,可以用textContains模糊匹配
      • new UISelector().textContains("包含text文本")
    • 同样可以用textStartsWith是以某个文本开头来匹配
      • new UiSelector().textStartsWith(“以text文本开头”)
    • 也可以用正则表达式textMatches匹配
      • new UiSelector().textMatches(“正则表达式”)

  • 组合定位
    • 例1:id与text属性组合
      • id_text = 'resourceId("com.baidu.yuedu:id/webbooktitle").text("小说")'
      • driver.find_element_by_android_uiautomator(id_text).click()
    • 例2:class与text属性组合
      • class_text = 'className("android.widget.TextView").text("图书")'
      • driver.find_element_by_android_uiautomator(class_text).click()

  • 父子关系定位 childSelector
    • 有时候不能直接定位某个元素,但是它的父元素很好定位,这时候就先定位父元素,通过父元素找儿子
    • son = 'resourceId("com.baidu.yuedu:id/rl_tabs").childSelector(text("股票))'
  • 兄弟定位 fromParent
    • 有时候父元素不好定位,但是跟他相邻的兄弟元素很好定位,这时候就可以通过兄弟元素,找到同一父级元素下的子元素
    • brther = 'resourceId("com.baidu.yuedu:id/lefttitle").fromParent(text("用户"))'

  • 实现滚动查找元素
    • 'new UiScrollable(new UiSelector().scrollable(true).instance(0)).scrollIntoView(new UiSelector().text("查找的文本").instance(0));'

7.3 滑动定位

8. appium显式等待机制

Wait等待

  • 强制等待: sleep 不推荐
  • 全局隐式等待
    • 在服务端等待
    • driver.implicitly_wait(TIMEOUT)
  • 显式等待
    • 在客户端等待
    • WebDriverWait(self.driver, 10).until(expected_conditions.visibility_of_element_located(LOCATOR))

显示等待

  • 显式等待
    • 显示等待与隐式等待相对,显示等待必须在每个需要等待的元素前面进行声明。
    • 是针对于某个特定的元素设置的等待时间,在设置时间内,默认每隔一段时间检测一次当前页面某个元素是否存在,
    • 如果在规定的时间内找到了元素,则直接执行,即找到元素就执行相关操作,
    • 如果超过设置时间检测不到则抛出异常。默认检测频率为0.5s,默认抛出异常为:NoSuchElementException
  • 显示等待用到的两个类:
    • WebDriverWait和expected_conditions两个类

  • 显式等待可以等待动态加载的ajax元素,显式等待需要使 ExpectedCondtions来检查条件
  • 一般页面上元素的呈现
    • title出现         首先出现title
    • dom树出现     presence,还不完整
    • css出现           (可见 visibility)
    • js出现,js特效执行       (可点击 clickable)
  • html文档是自上而下加载的,
  • js文件加载会阻塞Html内容的加载,有些JS异步加载的方式来完成js的加载
  • 样式表下载完成之后会跟之前的样式表一起进行解析,会对之前的元素重新渲染

  • WebDriverWait用法
    • WebDriverWait(driver, timeout,poll_frequency=0.5,ignored_exceptions=None)
    • driver: 浏览器驱动
    • timeout:最长超时时间,默认以秒为单位
    • poll_frequency: 检测的间隔步长,默认为0.5s
    • ignored_exceptions: 超时后的抛出的异常信息,默认抛出 NoSuchElementExeception异常。
  • WebDriverWait 的 until() 和 until_not()方法:
    • method: 在等待期间,每隔一段时间(__init__中的poll_frequency)调用这个传入的方法, 直到返回值不是False,
      message: 如果超时,抛出 TimeoutException, 将message传入异常
    • until_not:与 until相反, until是当某元素出现或什么条件成立则继续执行, until_not是当某元素消失或什么条件不成立,则继续执行,参数也相同。

expected_conditions类

  • presence_of_element_located 判断元素是否被加到了DOM树里,并不代表该元素一定可见
    • 用法: WebDriverWait().until(expected_conditions, presence_of_element_located(元素对象))
  • visibility_of_element_located 判断某个元素是否可见,可见代表元素非隐藏,并且元素的宽和高都不等于0
    • 用法:WebDriverWait().until(expected_conditions, visibility_of_element_located(元素定位符))

使用lambda表达式

  • WebDriverWait(driver,time).until(lambda x:x.find_element_by_id("someId")) 返回一个元素

显示等待案例

总结三种等待方式

  • 隐式等待,尽量默认都加上,时间限定在3-6s,不要太长,为了所有的find_element方法都有一个很好的缓冲
  • 显式等待,用来处理隐式等待无法解决的一些问题,比如:文件上传(可以设置长一点),文件上传需要设置20s以上,但是如果设置隐式等待,它会在每个find方法都等这么长时间,一旦发现没有找到元素,就会等20s以后才抛出异常,影响case的执行效率,这时候就需要用显式等待,显式等待可以设置的长一点
  • 强制等待:一般不推荐,前两种基本能解决绝大部分问题,如果某个控件没有任何特征,只能强制等待,这种情况比较少

9. 特殊控件toast识别

18
toast控件识别

toast介绍

  • Toast,简易的消息提示框
    • 为了给当前视图显示一个浮动的显示块,与dialog不同它永远不会获得焦点
    • Toast类的思想:尽可能不引人注意,同时还向用户显示信息希望他们看到
    • Toast显示的时间有限,Toast会根据用户设置的显示时间后自动消失。
    • Toast本身是个系统级别的控件,它归属于系统 settings,当一个app发送消息的时候,不是自己造出来的这个弹框,它是发给系统,,由系统统一进行弹框,这类的控件不在app内,需要特殊的控件识别方法

toast定位

  • appium使用uiautomator底层的机制来分析抓取toast,并且把toast放到控件树里面,但本身并不属于控件。
  • automationName:uiautomator2
  • getPageSource是无法找到的
  • 必须使用xpath查找
    • //*[@class='android.widget.Toast']
    • //*[contains(@text,"xxxxx")]
private void addToastMsgToRoot(CharSequence tokenMSG){
    AccessibilityNodeInfo node =AccessibilityNodeInfo .obtain();
    node.setText(tokenMSG);
    node.setClassName(Toast.class.getName());
    node.setPackageName("com.android.settions");
    
    this.children.add(new UiAutomationElement(node /* Accessibil....))
}

在这里插入图片描述
在这里插入图片描述

toast定位案例

10. appium属性获取与断言

10.1 get attribute原理分析

10.2 属性命名规则

Get_attribute原理分析



源代码

源代码分析
在这里插入图片描述

断言

连按此项以编辑

  • 普通断言 Assert
  • Hamcrest 断言

普通断言

hamcrest断言

  • github地址:https://github.com/hamcrest/PyHamcrest
  • hamcrest框架介绍
    • Hamcrest是一个为了测试为目的,能组合成灵活表达式的匹配器类库。用于编写断言的框架,使用这个框架编写断言,提高可读性及开发测试的效率
    • Hamcrest提供了大量被称为“匹配器”的方法。每个匹配器都设计用于执行特定的比较操作。
    • Hamcrest的可扩展性强,让你能够创建自定义的匹配器。
    • 支持多种语言,java,python,ruby,object-c,php,erlang,swift
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

15 移动端app自动化测试 - 软件测试 的相关文章

  • 在 sympy 绘图中,如何获得具有固定纵横比的绘图?

    如果我用这个片段画一个圆 from sympy import x y symbols x y p1 plot implicit Eq x 2 y 2 1 aspect ratio 1 1 我会得到一个像这样的图形窗口 现在长宽比不是我所期望
  • Python 如果 kwargs 中的 key 并且 key 为 true

    if force in kwargs and kwargs force is True 感觉应该有更好的方法来编写这个条件 因为我重复了键和变量 假设您确实想检查返回的关键字参数是否is True 这是另一种稍微不同的方式 if kwarg
  • Python绕相机轴旋转图像

    假设我有一个图像 是在对某些原始图像应用单应性变换 H 后获得的 未显示原始图像 将单应性 H 应用于原始图像的结果是该图像 我想围绕合适的轴 可能是相机所在的位置 如果有的话 将此图像旋转 30 度以获得此图像 如果我不知道相机参数 如何
  • Python中非常大的整数的math.pow是错误的[重复]

    这个问题在这里已经有答案了 我试图通过计算一个整数的非常大的幂来打印一个非常大的数字 尽管我的代码是正确的 但我没有观察到所需的输出 一般来说 Python解释器可以打印系统内存支持的非常大的整数 考虑到这个假设 下面是我正在运行的代码 a
  • Python/Scipy 2D 插值(非均匀数据)

    这是我上一篇文章的后续问题 Python Scipy 插值 地图坐标 https stackoverflow com questions 5124126 python scipy interpolation map coordinates
  • 如果工作表不存在,Pandas 将工作表附加到工作簿,否则覆盖工作表

    我正在使用 pandas 更新现有的 Excel 工作簿 当使用ExcelWriter对象 我可以覆盖工作表 如果存在 否则创建一个新工作表吗 我的代码附加了新工作表 但是当我尝试覆盖现有工作表时 它会附加一个名称略有不同的新工作表 例如
  • 如何在Python中重命名virtualenv?

    我拼错了名字virtualenv使用以下方法初始化它 virtualenv vnev 我实际上打算创建一个名为的环境venv 尝试重命名后vnev文件夹到venv 我发现这并没有提供太多帮助 激活环境的名称仍然重命名旧的vnev mv vn
  • 桨在移动时留下痕迹(Pygame Pong 游戏)[重复]

    这个问题在这里已经有答案了 我的游戏中的球拍有问题 每次我试图移动它时 桨都会留下一条 痕迹 我想这是因为我的代码没有删除旧位置的前一个桨 如果是的话怎么删除之前的呢 我应该使用blit Code import pygame sys ran
  • Python 宏:用例?

    如果 Python 有一个类似于 Lisp Scheme 的宏工具 比如元Python https code google com p metapython 你会如何使用它 如果您是一名 Lisp Scheme 程序员 您会使用宏来做什么
  • Python:使用Excel CSV文件仅读取某些列和行

    虽然我可以读取 csv 文件而不是读取整个文件 但如何仅打印某些行和列 想象一下这是 Excel A B C D E State Heart Disease Rate Stroke Death Rate HIV Diagnosis Rate
  • Django - 从时间戳获取不同的日期

    我正在尝试按日期过滤用户 但直到我可以找到数据库中用户的第一个和最后一个日期为止 虽然我可以让我的脚本稍后过滤掉重复项 但我想从一开始就使用 Django 来完成此操作distinct因为它显着减少 我试过 User objects val
  • Python 多处理:全局对象未正确复制到子级

    前几天我回答了一个关于SO的问题 https stackoverflow com q 67047533 1925388关于并行读取 tar 文件 这是问题的要点 import bz2 import tarfile from multipro
  • 为什么变量不在循环外更新?

    无法弄清楚为什么结果中的第一个键是 abc 而不是我期望的 c 我使用的是Python 3 6 4 数据结构很奇怪 因为我删除了不相关的键和值 f replace ab r data abc 1 def 2 ghi 3 jkf 4 lmn
  • “gi.repository.Gtk”对象没有属性“gdk”

    我正在尝试使用 GTK 创建多线程 需要 Gtk gdk 但我收到有关没有 gdk 属性的错误 我正在使用带有 Raspbian 的 Raspberry Pi 这就是我导入 GTK 库的方式 try import pygtk pygtk r
  • 如何在Python中仅列出顶级目录?

    我希望能够仅列出某个文件夹内的目录 这意味着我不需要列出文件名 也不需要其他子文件夹 让我们看看一个例子是否有帮助 在当前目录中我们有 gt gt gt os listdir os getcwd cx Oracle doc DLLs Doc
  • 编写 CherryPy 装饰器以进行授权

    我有一个cherrypy应用程序 在某些视图上我想开始只允许某些用户查看它们 并将其他任何人发送到需要授权的页面 有没有办法使用自定义装饰器来做到这一点 我认为这将是最优雅的选择 这是我想做的一个基本示例 class MyApp autho
  • 添加条件计数器:基于其他列的值的计数器列

    我有一张这样的桌子 id id2 val a red apple a red orange b blue fish c violet beef a yellow banana a black pork 我想根据 id 和 id2 的值创建一
  • 如何从集合中检索元素而不删除它?

    假设如下 gt gt gt s set 1 2 3 我如何获得一个值 任何值 s不做s pop 我想将该项目保留在集合中 直到我确定可以删除它 这只有在异步调用另一个主机之后才能确定 又快又脏 gt gt gt elem s pop gt
  • centos上无法安装Pillow

    我上面有 centos 6 3 和 python 2 6 当我尝试通过 easy install 安装它时 出现以下错误 imaging c 76 20 error Python h No such file or directory In
  • 写入文件的正确方法?

    我想知道这样做是否有什么区别 var1 open filename w write Hello world 并做 var1 open filename w var1 write Hello world var1 close 我发现没有必要

随机推荐