测试开发 | AppCrawler 自动遍历测试实践(三):动手实操与常见问题汇总

news2024/11/26 7:41:51

上两篇文章介绍了自动遍历的测试需求、工具选择和 AppCrawler 的环境安装、启动及配置文件字段基本含义,这里将以实际案例更加细致的说明配置文件的用法和一些特殊场景的处理。

实操演示

常规使用

下面我们继续之前的例子,在雪球搜索框输入搜索内容后的页面开始:

  • testcase:设置测试用例,输入 alibaba 后,点选"阿里巴巴" 

yaml 写法如下:

testcase:  name: "XueQiuTestDemo AppCrawler"  steps:  - { xpath: "//*[contains(@resource-id,'image_cancel')]", action: click }  - xpath: home_search    action: click  - xpath: search_input_text    action: alibaba  - { xpath: 阿里巴巴, action: click }

  • selectedList:遍历范围设定 

    接上一步点选"阿里巴巴"后到达如下界面: 

我们先看demo配置文件中的原始写法,如下: 

selectedList:- given: []  when: null  then: []  xpath: "//*[contains(name(), 'Button')]"  action: null  actions: []  times: 0- given: []  when: null  then: []  xpath: "//*[contains(name(), 'Text') and @clickable='true' and string-length(@text)<10]"  action: null  actions: []  times: 0- given: []  when: null  then: []  xpath: "//*[@clickable='true']/*[contains(name(), 'Text') and string-length(@text)<10]"  action: null  actions: []  times: 0- given: []  when: null  then: []  xpath: "//*[contains(name(), 'Image') and @clickable='true']"  action: null  actions: []  times: 0- given: []  when: null  then: []  xpath: "//*[@clickable='true']/*[contains(name(), 'Image')]"  action: null  actions: []  times: 0- given: []  when: null  then: []  xpath: "//*[contains(name(), 'Image') and @name!='']"  action: null  actions: []  times: 0- given: []  when: null  then: []  xpath: "//*[contains(name(), 'Text') and @name!='' and string-length(@label)<10]"  action: null  actions: []  times: 0

原始文件中将所有可点击的控件类型都包括了进去,再加上了部分 text 长度的限制 现在我们按照自己平常的简便写法重新编写,先设置所有 clickable 等于 true 的控件进行点击:

在 Android 中,一个控件如果绑定了用户响应行为的事件,那么 clickable 的属性值就是 true

selectedList: - { xpath: "//*[@clickable='true']", action: click }
  • blackList:黑名单,将不想要被点击的元素加入黑名单中 

    配置文件原始写法如下,表示将带有2位数字的排除在外,可能是App中包含了很对关于股价展示的,不需要挨个点击:

blackList:- given: []  when: null  then: []  xpath: ".*[0-9]{2}.*"  action: null  actions: []  times: 0

我们现在希望不要点击到叉号❌和取消按钮,否则会跳出此页面,那么就可以把其加入黑名单中,如下: 

blackList: - xpath: ".*[0-9]{2}.*" - xpath: //*[@resource-id='action_delete_text'] - xpath: //*[@resource-id='action_close']
  • firstList: 优先被遍历

    这里我们设置让text包含"股票"的优先遍历 

firstList: - { xpath: "//*[contains(@text,'股票')]", action: click }
  • lastList:最后被点击

    在页面中有很多标签页(例如综合、股票、用户、组合): 

每个标签页下面对应着很多控件需要被操作,可是在当前页面下的控件未被遍历完的时候就有可能会点击到其他标签页中了,我们希望的是在一个标签页下完全遍历结束后最后再点击标签控件,这个就可以借助lastList来完成,让元素在点进标签页后的内容为最后遍历

lastList: - { xpath: "//*[contains(@resource-id,'ti_tab_indicator')]//*", action: click }

  • backButton: 当所有元素都被点击后默认后退控件定位

    AppCrawler是不知道后退按钮是哪一个的,这个可能会造成的一种情况是,当我们进入一个页面时,还没有对这个页面完全遍历就点到了后退按钮,这样就会造成测试不充分 


因此我们可以给它设置一个默认的后退按钮,使所有事件完成后再 back
 

backButton: - { xpath: "//*[contains(@resource-id,'action_back')]", action: click }

这里还要说明一点,如果 backButton 没有配置,当遍历第一个页面的时候被点击了,再下一个页面的时候,因为已经被遍历过了,所以就不会优先去遍历这个回退按钮了,对后面的遍历测试没有大的影响,可能就是第一个页面会有遍历不完全的概率。

  • maxDepth: 遍历的最大深度

    有时候我们的页面层次可能很深,每次遍历测试的需求可能不同,有时候可能需要在短时间内测试主要常用界面的功能,有时候可能需要全面的测试,所以测试的深度就不相同,我们可以依靠 maxDepth 来进行需求定制,这里以遍历 2 层深度为例:

maxDepth: 2

特殊技巧

  • findBy:定位方式的选择

    findBy 可以设置定位方式,有 defaultandroididxpth 方式可选,默认状态会自动判断是否是要 Android 定位或者 iOS 定位。当我们的定位很精准的时候,用默认的 default 速度会快一点;若是定位符写的不是很精准,在切换到 Android 定位的时候可能找不到,这个时候就可以尝试将其设置为 Xpath方式定位。

findBy: "xpath"
  • defineUrl = List[String]():用来确定url的元素定位 xpath,他的 text 会被取出当做 url 因素;就是说如果想要当前的页面布局与某个控件之间有层级关系,给定一个标记控件,以此来区分不同的界面(语言的描述怎么样都有点晦涩,还是结合下面的示例来理解吧。。。)

有时候我们会遇见这种情况:设置了 clickable 未 true 的控件都被遍历,可是运行时发现很多控件都没有被遍历到,一般这种情况有一下两种原因:

  • 元素属性 clickable 本身就为 false 或者它的父节点等都为 false,这样自然是无法遍历到的。

  • 还有一种情况是同属性的控件在两个tag页面都存在,在其中一个tag页遍历一遍之后,再到下一个tag页中就会默认已经遍历,不会再进行遍历,如下这种:

在“股票”和“用户”tag页中,“加自选”和“关注”控件的clickableid属性一样。

他们所属的页面属性也一样,所以会被看做是同一个页面下的同一个控件:


如上这种情况肯定不是我们想要的,我们想要它在股票和用户页都分别进行遍历,更好的覆盖测试,那么就要借助于 defineUrl 了;

1)按照上面的介绍,我们首先要找一个标志控件,用来做页面的区分,那么我们首先想到的就是从“股票”和“用户”这两个 tag 标签属性上来找,遗憾的是最终发现这两个控件的属性全都一毛一样:

 

2)接着我们就必须从 tag 页内部来找标志控件了,我们发现在“股票”和“用户”页中搜索出来的结果名称的 id 是不同的:

3)上面介绍过了 defineUrl 是取的 text 属性值作为标志区分,所以这里取股票页的第一个元素“阿里巴巴”和用户页的第二个元素“阿里巴巴四十大盗”,

具体 yaml 写法如下:

defineUrl: - (//*[contains(@resource-id, "stockName")])[1]- (//*[contains(@resource-id, "user_name")])[2]

缺点:上面的做法虽然解决了页面区分的问题,但是有一个缺点就是我们定义了遍历的深度,然而使用 defineUrl 之后将每个标志符在的页面都视为一个新的 activity,因此遍历深度就会从这里开始重新计算

4)继续解决上述的缺点,我们可以在 clickable 之前指定所属的页面,当判断不在此页面后就会自动跳回

selectedList: - { xpath: "//*[@resource-id='com.xueqiu.android:id/ll_search_result']//*[@clickable='true']//*", action: click }

5)另外我们之前在 selectList 中写了 clickable=true, 而 clickable=true 通常只是布局元素,布局元素一般是没有任何属性的,不知道控件里包含什么,这样在截图和生成报告的时候就会造成不精准,截图中的步骤框就很可能选择错误,对我们定位分析问题造成困扰;

所以我们要继续往下找标志符,以 Text 作为定位标志符:

selectedList: - { xpath: "//*[@resource-id='com.xueqiu.android:id/ll_search_result']//*[@clickable='true']//*[contains(@class,'Text')]", action: click }

用 Text 作为标志符以后所有的 Text 属性都会遍历一遍,还可以进一步优化,使用id非空作为判定条件,并且通常研发将控件设置 id 的话很可能此控件有关键的作用

selectedList:
 - { xpath: "//*[@resource-id='com.xueqiu.android:id/ll_search_result']//*[@clickable='true']//*[@resource-id!='']", action: click }

6)按照上面的写法又引发了新的问题,就是 id 不为空的时候,我们的 tag 控件无法被选中了,因为 tag 控件的 id 正好为空:

因此我们又需要对 selectedList 进行修改,单独增加一条判定条件用来过滤出 tag 控件;我们注意到它们同属一片有 id 的区域,并且各自自身有 text:

修改后的selectedList如下:

selectedList: - { xpath: "//*[@clickable='true']//*[contains(@class,'Text')]", action: click } - { xpath: "//*[contains(@resource-id, 'ti_tab_indicator')]//*[contains(@class,'Text')]",

  • tagLimitMax:最大的点击次数

    有时候页面中可能会有多个相同类型的控件,这些控件之间可能只是展示的信息不同,其他功能属性都一直,那么为了保证测试效率可以只设置让它被点击少数次或者一次,通过 tagLimitMax 设置即可。 

tagLimitMax: 1

缺点:这个设置是一个全局的,一旦设置,那么所有的同类型的控件都只会被点击一次,但是像上个例子中的 4 个tag标签控件虽然是同类型的,但是每一个都需要被点击一次,这样显然就不符合我们的需求了,这个时候就需要 tagLimit 参数了

  • tagLimit:自定义控件类型的点击次数

tagLimit: - xpath: //*[contains(@resource-id, 'ti_tab_indicator')]//*[contains(@class,'Text')]  action: click  times: 4

  • triggerActions:触发器,特定条件触发执行动作的设置 这个参数是一个非常有用的参数,比如我们可能会遇到如下的情况

    - 广告、升级弹框在测试过程中突然出现

    - 某些动作需要输入

    - 某些动作需要特定次数的操作

而这个时候就轮到 triggerActions 大显身手了,它可以对特定的控件指定特定的动作和次数,在每一次遍历执行前都会先执行一遍 triggerActions,它不像 testcase 是个流形式的,执行完就结束了,triggerActions 会一直伴随着执行

  • - 这样每次出现弹框都会被处理

  • - 测试中途碰到了账号密码输入框需要输入的可以提前在triggerActions中设置

不知道大家还记得在刚开始运行的时候,因为在已进入主页的时候就会有升级弹框出来,所以那时候我在 testcase 中加入了步骤将其点掉,但是如果在其他页面再次弹出的话就无法处理,现在以此为例,将其加入 triggerActions

triggerActions: - xpath: //*[contains(@resource-id,'image_cancel')]   action: click   times: 1

常见问题补充


1. App 运行比较慢,容易超时怎么办?

答:AppCrawler 默认每次操作时会等待 500ms; 通过 triggeraction 来解决需要等待的条件,xpath 为进度条,action 为 sleep 1s。

2. tagLimit 会限制同属性但不同层级的元素吗?

答:tagLimit 限制的是相同的父节点层级,不管属性,是看布局的层级。

3. 如何防止遍历的时候不小心跳到别的应用?跳到别的应用后怎么回来?

答:会自动跳转回来的。除非设置了 App 的白名单

4. 页面需要在当前页不停滑动加载测试

答:遍历完当前页后用 afterpage 参数设置滑动

5. firstList 和 lastList 可以写多个表达式吗?他们是如何执行的?

答:顺序是这样排列的

6. app 运行比较慢,容易超时怎么办?

答:AppCrawler 默认每次操作时会等待 500ms;通过 triggeraction 来解决需要等待的条件,xpath 为进度条,action 为 sleep 1s

7. tagLimit 会限制同属性但不同层级的元素吗?

答:tagLimit 限制的是相同的父节点层级,不管属性,是看布局的层级

8. 如何防止遍历的时候不小心跳到别的应用?跳到别的应用后怎么回来?

答:会自动跳转回来的。除非设置了 App 的白名单

9. 页面需要在当前页不停滑动加载测试

答:遍历完当前页后用 afterpage 参数设置滑动

10. firstList 和 lastList 可以写多个表达式吗?他们是如何执行的?

答:顺序是这样排列的

firstList[0]firstList[1]排除lastList firstList之后剩下的元素lastList[0]lastList[1]backbutton

11. Appclawer ==>maxDepth:这个层级是如何定义的?

答:maxDepth 可以从 log 中看到,AppCrawler.log 中有一个 Stack 的输出,里面默认保存的是所有 activity 的栈记录。

Main

Main->UserProfile

Main->UserProfile->Login

Main

maxDepth是判断这个堆栈最长的长度,一旦超过就回退

推荐学习

AppCrawler 的使用就告一段落了。大家还有疑问,可以在文章末尾扫码入群一起交流。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/167819.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

代码随想录算法训练营第六天 | 哈希表理论基础,242.有效的字母异位词,349. 两个数组的交集, 202. 快乐数,1. 两数之和

第五天 周日 休息~【提醒补坑&#xff1a;链表总结还没写】一、参考资料哈希表理论基础文章连接&#xff1a;https://programmercarl.com/%E5%93%88%E5%B8%8C%E8%A1%A8%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%80.html有效的字母异位词题目链接/文章讲解/视频讲解&#xff1a;https:…

使用批处理__更改ip

1、使用.bat进行处理 echo off rem 测试更改ip netsh int ip set address "以太网 2" static 10.10.2.1 255.255.255.0 10.10.2.254 1 pause&exit 备注其他 echo #设静态IP netsh interface ip set address name"本地连接" sourcestatic addr192.16…

大坝安全监测解决方案 水库大坝安全监测系统改造工程方案

平升电子大坝安全监测系统根据SL551-2012《土石坝安全监测技术规范》的整编要求&#xff0c;设置了变形监测、渗流监测、环境量监测。借助大坝安全监测系统可及时了解大坝的工作性态和水库可能存在的事故隐患&#xff0c;为大坝安全管理与水库运行调度提供了准确、及时的现场信…

ElasticSearch7.10配置Search-Guard之配置用户

ElasticSearch7.10配置Search-Guard之配置用户 配置sg_internal_user.yml 密码是&#xff1a;elastic jode:hash: $2y$12$nUzkcjdnufzvI1HlmN7xSuND3skGhmwV5le5IINejz.asMFpLYNRybackend_roles:- "hr_department"psmith:hash: $2y$12$nUzkcjdnufzvI1HlmN7xSuND3sk…

[标准库]STM32F103R8T6 标准库配置RCC时钟和超频

前言 这篇博客总结一下学习到的配置时钟的方法。 从启动文件来看&#xff0c;MCU复位之后&#xff0c;执行到SystemInit()这个函数之后&#xff0c;会进入系统初始化设置&#xff0c;比如根据当前的MCU型号进入不同的条件编译语句&#xff0c;再配置相应的寄存器初始值&#…

mysql之一条mysql语句时如何执行的

请把连接器的功能说明一下? 连接器负责建立客户端和mysql服务器之间的连接.当客户端在中断输入连接命令(mysql -h -u -p),传输层使用tcp协议,通过三次握手建立连接. 如果mysql服务服务没有启动,会报错: 如果mysql服务正常启动,完成三次握手,在传输层建立连接后,会进行密码验证…

【云原生】k8s 一键部署(ansible)

文章目录一、概述二、Ansible 部署1&#xff09;开启记录日志2&#xff09;去掉第一次连接ssh ask确认3&#xff09;配置hosts三、开始编排 ansible playbook1&#xff09;创建目录2&#xff09;节点初始化3&#xff09;安装 docker4&#xff09;安装 k8s 相关组件5&#xff09…

2022 年 12 月区块链操作系统的开发回顾

正在寻找区块链操作系统组件的最新进展&#xff1f;你找对地方了&#xff01;正如在我们的路线图文章中所描述的那样&#xff0c;我们一直在朝着定期且频繁的更新方向发展着&#xff0c;以便让我们的社区能够及时的了解到我们取得的进展&#xff0c;以及将区块链操作系统提升到…

新年喜报 再添殊荣 加速科技荣获浙江省“专精特新”企业认定

新年伊始&#xff0c;杭州市经济和信息化局公布了2022年度浙江省专精特企业名单。杭州加速科技有限公司&#xff08;以下简称“加速科技”&#xff09;凭借在技术创新、产品研发、精细化程度、经营能力、拓展潜力等多方面的优势&#xff0c;荣获浙江省“专精特新”企业荣誉称号…

一个人,一座城,你到底在乎什么?Python 爬虫告诉你!

大家好&#xff0c;我是安果&#xff01;有时候&#xff0c;我们想知道生活在这座城市的人每天交流的事情&#xff0c;然后对数据进行一些分析&#xff0c;方便我们更好地了解城市的特征及居民的需求以重庆为例&#xff0c;最火爆的论坛是购物狂&#xff0c;每天都有大量的帖子…

求解带不确定事件的FJSP的多目标强化学习框架

文献&#xff1a;Hao Wang, Junfu Cheng, Chang Liu, Yuanyuan Zhang, Shunfang Hu, Liangyin Chen,Multi-objective reinforcement learning framework for dynamic flexible job shop scheduling problem with uncertain events,Applied Soft Computing,Volume 131,2022,1097…

超级详细的python知识点及练习题(附答案)

今天咱们继续来学习python的小知识吖&#xff0c;上一次木有看的同学请看&#xff1a;python8大核心语句 作者&#xff1a;阿玥的小东东 学习&#xff1a;python&#xff0c;正在学习c 主页&#xff1a;阿玥的小东东 目录 1.复习及易错&#xff0c;快来学习&#xff01;&#…

基于python手撕实现BP 神经网络实现手写数字识别

本项目使用python实现全连接网络和梯度优化 方向传播并且实现了 手写数字识别项目: 神经网络 model 先介绍个三层的神经网络,如下图所示输入层(input layer)有三个 units( 为补上的 bias,通常设为

线程池ThreadPoolExecutor源码解析

参考视频 首先回顾一下创建线程等的三种方式 第一个是直接继承Thread类&#xff0c;重写run方法&#xff0c;这个其实内部也是继承了Runnable接口重写run方法。 比如&#xff1a; public class MyThread extends Thread{Overridepublic void run() {System.out.println("…

论文分享-《基于数据驱动多输出 ARMAX 建模的高炉十字测温中心温度》

1.简介 最近在学习研究NARMAX&#xff0c;故也分享下自己看的一篇论文。 2018 年 3 月 的《基于数据驱动多输出 ARMAX 建模的高炉十字测温中心温度》。主要是采用NARMAX模型进行预测&#xff0c;多输入多输出&#xff0c;有5个输出&#xff0c;预测中心五个点位的温度。下面讲…

计算机 - - - 局域网共享文件夹,局域网传输文件(待完善)

win10局域网共享文件夹 A电脑: 共享文件夹的电脑 B电脑: 访问共享文件夹的电脑 操作完成后, B电脑可以下载A电脑中的文件, B电脑可以修改删除, B电脑可以上传B电脑的文件到A电脑. A电脑 找到要共享的文件夹, 例如我要共享文档(E:), 我要把文档(E:)中的所有文件都让B电脑访问…

Python - 数据容器str(字符串)

目录 字符串的定义 字符串的常用操作 查找特定字符串的下标索引值 index 字符串的替换 replace 字符串的分割 split 字符串的规整操作 strip 统计字符串中某字符串的出现次数 count 统计字符串的长度 len 字符串切片 [起始下标:结束下标:步长] 字符串的定义 和其它容器…

银行案例分析:识别个人贷款客户画像,实现精准营销与风险防范

作为商业银行最主要的业务活动&#xff0c;也是收益最大的活动&#xff0c;贷款于银行的重要性不言而喻。又由于个人贷款是银行贷款不可或缺的一部分&#xff0c;那么了解个人贷款客户画像就有助于银行对客户进行精准销售和风险识别。 # 选手介绍 #张昊泽&#xff1a;亚利桑那州…

Pycharm入门搭建Django 项目

一、环境准备 1、pycharm版本 2、python版本 二、创建项目 击左上角的 File -> New Project 点击Create创建完成之后页面等待下载环境 查看Django的版本 python -m django --version 启动项目 python manage.py runserver 三、后记 在启动 Django 项目的时候我发现控制台…

【PaaS】分享一家最近发现的宝藏Paas厂家

目录 一、结识独自开 二、独自开的介绍 三、独自开的需求 四、独自开注册流程 五、神仙公司独自开 一、结识独自开 算是机缘巧合&#xff0c;我被C站白佬拉入了他的聊天群&#xff0c;群内均是来自于CSDN的不同领域的优质作者&#xff0c;其中不乏相关领域工作多年的老工程…