热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Android目录遍历工具|AppCrawler自动化测试进阶(第二部分):个性化配置详解

终于迎来了“足不出户也能为社会贡献力量”的时刻,但有追求的测试工程师绝不会让自己的生活变得乏味。与其在家消磨时光,不如利用这段时间深入研究和提升自己的技术能力,特别是对AppCrawler自动化测试工具的个性化配置进行详细探索。这不仅能够提高测试效率,还能为项目带来更多的价值。

终于到了“啥也不干躺在家就能给社会做贡献”的时候,但有梦想的测试人从不会让自己的生活变得无聊!与其宅在家里数瓜子壳,还不如利用整块时间提升测试开发技能!

1fcdf6c0a081f096d4fe2c23efbf4612.png

定制化配置

自动遍历测试技术以及工具该如何选择和快速入门?经过对比和需求,最终选择测试架构师思寒大佬的 AppCrawler 作为自动遍历测试的工具。以下就分享 AppCrawler 自动遍历测试的一些最佳实践经验。

模板文件生成

运行命令java -jar appcrawler-2.4.0-jar-with-dependencies.jar --demo, 会在当前目录下生成一个 demo.yml 文件,这个文件就是我们进行定制化的配置文件模板:

#执行命令生成demo.yaml模板配置文件$ java -jar appcrawler-2.4.0-jar-with-dependencies.jar --demo2019-12-01 21:33:35 INFO [AppCrawler$.86.main]----------------AppCrawler 2.4.0 [霍格沃兹测试学院特别纪念版]Appium 1.8.1 Java8 testedapp爬虫, 用于自动遍历测试. 支持Android和iOS, 支持真机和模拟器项目地址: https://github.com/seveniruby/AppCrawler移动测试技术交流: https://testerhome.com联络作者: seveniruby@testerhome.com (思寒)致谢: 晓光 泉龙 杨榕 恒温 mikezhou yaming116 沐木--------------------------------2019-12-01 21:33:35 INFO [AppCrawler$.223.parseParams] use default appium address 47232019-12-01 21:33:35 INFO [AppCrawler$.230.parseParams] appium address = Some(http://127.0.0.1:4723/wd/hub)2019-12-01 21:33:35 INFO [AppCrawler$.242.parseParams] result directory = 201912012133352019-12-01 21:33:36 INFO [AppCrawler$.286.parseParams] you can read /Users/qinzhen/Documents/TestDev/AppCrawler/demo.yml for demo#查看配置文件已生成$ lsappcrawler-2.4.0-jar-with-dependencies.jardemo.yml

  • 打开配置文件demo.yaml如下:

---pluginList: []saveScreen: truereportTitle: ""resultDir: "20191201213335"waitLoading: 500waitLaunch: 6000showCancel: truemaxTime: 10800maxDepth: 10capability: noReset: "true" fullReset: "false" appium: "http://127.0.0.1:4723/wd/hub"testcase: name: "TesterHome AppCrawler" steps: - given: [] when: null then: [] xpath: "/*" action: "Thread.sleep(5000)" actions: [] times: 0selectedList:- given: [] when: null then: [] xpath: "//*[contains(name(), &#39;Button&#39;)]" action: null actions: [] times: 0- given: [] when: null then: [] xpath: "//*[contains(name(), &#39;Text&#39;) and &#64;clickable&#61;&#39;true&#39; and string-length(&#64;text)<10]" action: null actions: [] times: 0- given: [] when: null then: [] xpath: "//*[&#64;clickable&#61;&#39;true&#39;]/*[contains(name(), &#39;Text&#39;) and string-length(&#64;text)<10]" action: null actions: [] times: 0- given: [] when: null then: [] xpath: "//*[contains(name(), &#39;Image&#39;) and &#64;clickable&#61;&#39;true&#39;]" action: null actions: [] times: 0- given: [] when: null then: [] xpath: "//*[&#64;clickable&#61;&#39;true&#39;]/*[contains(name(), &#39;Image&#39;)]" action: null actions: [] times: 0- given: [] when: null then: [] xpath: "//*[contains(name(), &#39;Image&#39;) and &#64;name!&#61;&#39;&#39;]" action: null actions: [] times: 0- given: [] when: null then: [] xpath: "//*[contains(name(), &#39;Text&#39;) and &#64;name!&#61;&#39;&#39; and string-length(&#64;label)<10]" action: null actions: [] times: 0firstList: []lastList:- given: [] when: null then: [] xpath: "//*[&#64;selected&#61;&#39;true&#39;]/..//*" action: null actions: [] times: 0- given: [] when: null then: [] xpath: "//*[&#64;selected&#61;&#39;true&#39;]/../..//*" action: null actions: [] times: 0backButton:- given: [] when: null then: [] xpath: "Navigate up" action: null actions: [] times: 0triggerActions:- given: [] when: null then: [] xpath: "share_comment_guide_btn" action: null actions: [] times: 0xpathAttributes:- "name"- "label"- "value"- "resource-id"- "content-desc"- "instance"- "text"sortByAttribute:- "depth"- "list"- "selected"findBy: "default"defineUrl: []baseUrl: []appWhiteList: []urlBlackList: []urlWhiteList: []blackList:- given: [] when: null then: [] xpath: ".*[0-9]{2}.*" action: null actions: [] times: 0beforeRestart: []beforeElement:- given: [] when: null then: [] xpath: "/*" action: "Thread.sleep(500)" actions: [] times: 0afterElement: []afterPage: []afterPageMax: 2tagLimitMax: 2tagLimit:- given: [] when: null then: [] xpath: "确定" action: null actions: [] times: 1000- given: [] when: null then: [] xpath: "取消" action: null actions: [] times: 1000- given: [] when: null then: [] xpath: "share_comment_guide_btn_name" action: null actions: [] times: 1000assertGlobal: []

执行参数

同样&#xff0c;还是以雪球 App 为例&#xff0c;以实际操作运行来解释配置文件中各个参数的含义和用法

  • capability 设置: 与 appium 完全一致,但要注意这里默认有 noReset: "true" 和 appium: "http://127.0.0.1:4723/wd/hub" 属性,配置完成如下

capability: noReset: "false" fullReset: "false" appium: "http://127.0.0.1:4723/wd/hub" appPackage: com.xueqiu.androi appActivity: .view.WelcomeActivityAlias automationName: uiautomator2 autoGrantPermissions: true

这里再介绍两个很有趣也很有用的参数&#xff1a;

dontStopAppOnReset: true ;这个参数允许我们在某个页面继续执行遍历&#xff0c;比如我们希望App先进入到某个页面后再进行遍历&#xff0c;或者当一个session结束后继续下一个session的时候我们希望不要杀死App重新执行&#xff0c;而是继续上一次结束的页面开始执行

ignoreUnimportantViews: 这个参数设置为true的时候可以忽略不重要的view&#xff0c;加速pageSource的加载&#xff0c;加快测试速度

  • testcase: 用于启动APP后的基础测试用例
12af459ced55406f30a835b72206c724.png

允许我们以 given、when、then 的形式指定操作&#xff0c;如果学习过 Java 的接口自动化框架 rest-assured 话可以很容易理解这三个参数表达的含义&#xff1a;

  • given : 所有的先决条件&#xff0c;给定一个条件&#xff0c;只有条件成立的时候才完成后面的操作(实际用的较少)
  • when : 先决条件成立后的行为&#xff0c;对什么事件做什么事情
  • then : 断言集合&#xff0c;事件结束后对结果断言

具体写法如下&#xff1a;

testcase: name: "TesterHome AppCrawler" steps: - when: xpath: //* action: driver.swipe(0.5, 0.8, 0.5, 0.2) - when: xpath: //* action: driver.swipe(0.5, 0.2, 0.5, 0.8) then: - //*[contains(&#64;text, &#39;美股&#39;)]

ebe3347805b75b54a784682f370433c3.png

另外实际使用中我们会经常使用简写形态

  • 直接使用 xpath 对应 when 里面的 xpath
  • 直接使用 action 对应 when 里面的 action 具体写法如下&#xff1a;

- xpath: 自选 action: click then: - //*[contains(&#64;text, &#39;美股&#39;)]

c0a36a4d4ffcb783b503556ad7fe14a1.png

注&#xff1a;定位模式除了可以使用 xpath 之外还可以使用正则和包含关系&#xff0c;只不过经常使用的是 xpath&#xff0c;也更为严谨&#xff1b;

  • 正则&#xff1a;使用^开头的就认定为正则&#xff0c;^确定$&#xff0c;^.*输入密码
  • 包含&#xff1a;可以使用元素其中包含的内容进行定位; 密码&#xff0c;输入&#xff0c;请

这里以雪球首页搜索框输入 alibaba 的简单场景举例&#xff0c;在搜索前还需要处理掉升级弹框&#xff0c;修改完成如下:

testcase: name: "XueQiuTestDemo AppCrawler" steps: - { xpath: "//*[contains(&#64;resource-id,&#39;image_cancel&#39;)]", action: click } - xpath: home_search action: click - xpath: search_input_text action: alibaba

如上的 testcase 写法还要多说几句&#xff1a;

  • 也可以使用 {} 将需要执行的事件包裹起来&#xff0c;元素定位符和操作 action 时间用逗号隔开
  • {} 内若使用 xpath 表达式的话需要加双引号
  • xpath 中直接写 id 或 text 文本信息&#xff0c;就会默认使用包含去查找
  • 需要点击的事件要明确指明 click&#xff0c;某则会报错&#xff1b;虽然思寒说过默认的 action 就是 click &#xff0c;但是经过实测发现在 2.4.0 版本上必须指明 action&#xff1a;click ; 很可能是思寒本地使用的内部版本经过了优化更新还未来得及开源到 GitHub上。

运行效果&#xff1a;

format,png

selectedList: 遍历范围设定

这里如果想设置让其点击所有可点击的TextView和ImageView控件,修改完成如下:

selectedList:- xpath: //android.widget.ImageView[&#64;clickable&#61;&#39;true&#39;]- xpath: //*[&#64;clickable&#61;&#39;true&#39; and contains(&#64;class,"Text")]

  • firstList: 优先被点击
  • lastList:最后执行 设置其最后才执行"确定"按钮,修改完成如下&#xff1a;

lastList:- { xpath: text_yes, action: click }

  • backButton: 当所有元素都被点击后默认后退控件定位
  • blackList&#xff1a;黑名单
  • triggerAction: 特定条件出发执行动作的设置;设置遇到重置密码输入框时输入123456abc两次,修改完成如下:

triggerActions:- { xpath: android.widget.EditText, action: 123456abc, times: 2 }

  • tagLimitMax: 全局设置,同类型的最多点击的次数;这里设置为2次

tagLimitMax: 2

  • tagLimit: 自定义控件类型的点击次数,这里设置对于ListView类型的只点击一次; 修改完成如下 &#xff1a;

- { xpath: "//*[contains(&#64;class, &#39;List&#39;)]//*", times: 1 }

  • maxDepth: 遍历的最大深度

assertGlobal&#xff1a;设置一个全局断言&#xff0c;例如可设置断言在当前App&#xff0c;如果包名不符合&#xff0c;就可能发生了崩溃&#xff0c;便会报错

注&#xff1a;执行参数比配置文件优先级高

到这里&#xff0c;appcrawler的基本语法和参数含义大致介绍了一遍&#xff0c;后面就是如何结合实际进行使用了。

(文章来源于霍格沃兹测试学院)



推荐阅读
  • 本文详细介绍了Java中org.neo4j.helpers.collection.Iterators.single()方法的功能、使用场景及代码示例,帮助开发者更好地理解和应用该方法。 ... [详细]
  • 本文详细介绍了 GWT 中 PopupPanel 类的 onKeyDownPreview 方法,提供了多个代码示例及应用场景,帮助开发者更好地理解和使用该方法。 ... [详细]
  • Explore a common issue encountered when implementing an OAuth 1.0a API, specifically the inability to encode null objects and how to resolve it. ... [详细]
  • 本文详细介绍了如何使用 Yii2 的 GridView 组件在列表页面实现数据的直接编辑功能。通过具体的代码示例和步骤,帮助开发者快速掌握这一实用技巧。 ... [详细]
  • 本文详细介绍了Java中org.eclipse.ui.forms.widgets.ExpandableComposite类的addExpansionListener()方法,并提供了多个实际代码示例,帮助开发者更好地理解和使用该方法。这些示例来源于多个知名开源项目,具有很高的参考价值。 ... [详细]
  • RecyclerView初步学习(一)
    RecyclerView初步学习(一)ReCyclerView提供了一种插件式的编程模式,除了提供ViewHolder缓存模式,还可以自定义动画,分割符,布局样式,相比于传统的ListVi ... [详细]
  • 本文详细介绍了 Dockerfile 的编写方法及其在网络配置中的应用,涵盖基础指令、镜像构建与发布流程,并深入探讨了 Docker 的默认网络、容器互联及自定义网络的实现。 ... [详细]
  • 本文介绍了如何使用JQuery实现省市二级联动和表单验证。首先,通过change事件监听用户选择的省份,并动态加载对应的城市列表。其次,详细讲解了使用Validation插件进行表单验证的方法,包括内置规则、自定义规则及实时验证功能。 ... [详细]
  • 数据库内核开发入门 | 搭建研发环境的初步指南
    本课程将带你从零开始,逐步掌握数据库内核开发的基础知识和实践技能,重点介绍如何搭建OceanBase的开发环境。 ... [详细]
  • 本文深入探讨了 Java 中的 Serializable 接口,解释了其实现机制、用途及注意事项,帮助开发者更好地理解和使用序列化功能。 ... [详细]
  • Android LED 数字字体的应用与实现
    本文介绍了一种适用于 Android 应用的 LED 数字字体(digital font),并详细描述了其在 UI 设计中的应用场景及其实现方法。这种字体常用于视频、广告倒计时等场景,能够增强视觉效果。 ... [详细]
  • 本章将深入探讨移动 UI 设计的核心原则,帮助开发者构建简洁、高效且用户友好的界面。通过学习设计规则和用户体验优化技巧,您将能够创建出既美观又实用的移动应用。 ... [详细]
  • 扫描线三巨头 hdu1928hdu 1255  hdu 1542 [POJ 1151]
    学习链接:http:blog.csdn.netlwt36articledetails48908031学习扫描线主要学习的是一种扫描的思想,后期可以求解很 ... [详细]
  • 本文详细介绍了Java中org.w3c.dom.Text类的splitText()方法,通过多个代码示例展示了其实际应用。该方法用于将文本节点在指定位置拆分为两个节点,并保持在文档树中。 ... [详细]
  • 本文详细介绍了macOS系统的核心组件,包括如何管理其安全特性——系统完整性保护(SIP),并探讨了不同版本的更新亮点。对于使用macOS系统的用户来说,了解这些信息有助于更好地管理和优化系统性能。 ... [详细]
author-avatar
如果-不曾开始_632
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有