热门标签 | 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;后面就是如何结合实际进行使用了。

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



推荐阅读
  • 在2020年8月19日的深度分析中,我们探讨了HTML标签中同时存在`a`标签的`href`和`onclick`属性时的触发顺序问题。此外,还讨论了如何在一个自适应高度的父级`div`中,使两个子`div`中的一个固定高度为300px,另一个自动填充剩余空间的方法。最后,文章详细介绍了JavaScript异步加载的多种实现方式,包括但不限于`async`、`defer`属性以及动态脚本插入技术,为开发者提供了丰富的技术参考。 ... [详细]
  • 2019年后蚂蚁集团与拼多多面试经验详述与深度剖析
    2019年后蚂蚁集团与拼多多面试经验详述与深度剖析 ... [详细]
  • 技术日志:深入探讨Spark Streaming与Spark SQL的融合应用
    技术日志:深入探讨Spark Streaming与Spark SQL的融合应用 ... [详细]
  • 在Spring框架中,基于Schema的异常通知与环绕通知的实现方法具有重要的实践价值。首先,对于异常通知,需要创建一个实现ThrowsAdvice接口的通知类。尽管ThrowsAdvice接口本身不包含任何方法,但开发者需自定义方法来处理异常情况。此外,环绕通知则通过实现MethodInterceptor接口来实现,允许在方法调用前后执行特定逻辑,从而增强功能或进行必要的控制。这两种通知机制的结合使用,能够有效提升应用程序的健壮性和灵活性。 ... [详细]
  • 本文深入探讨了 `ExpressionChangedAfterItHasBeenCheckedError` 错误的原因及其解决方案。通过分析 Angular 的变更检测机制,详细解释了该错误的发生条件,并提供了多种有效的应对策略,帮助开发者在实际开发中避免这一常见问题。 ... [详细]
  • Android ListView 自定义 CheckBox 实现列表项多选功能详解
    本文详细介绍了在Android开发中如何在ListView的每一行添加CheckBox,以实现列表项的多选功能。用户不仅可以通过点击复选框来选择项目,还可以通过点击列表的任意一行来完成选中操作,提升了用户体验和操作便捷性。同时,文章还探讨了相关的事件处理机制和布局优化技巧,帮助开发者更好地实现这一功能。 ... [详细]
  • Spring注解开发指南:@Resource与@Component详解 ... [详细]
  • 本文深入探讨了NDK与JNI技术在实际项目中的应用及其学习路径。通过分析工程目录结构和关键代码示例,详细介绍了如何在Android开发中高效利用NDK和JNI,实现高性能计算和跨平台功能。同时,文章还提供了从基础概念到高级实践的系统学习指南,帮助开发者快速掌握这些关键技术。 ... [详细]
  • 深入解析Spring框架中的双亲委派机制突破方法
    在探讨Spring框架中突破双亲委派机制的方法之前,首先需要了解类加载器的基本概念。类加载器负责将类的全限定名转换为对应的二进制字节流。每个类在被特定的类加载器加载后,其唯一性得到保证。然而,这种机制在某些场景下可能会限制灵活性,因此Spring框架提供了一些策略来突破这一限制,以实现更加动态和灵活的类加载。这些策略不仅能够提升系统的可扩展性,还能在复杂的运行环境中确保类的正确加载和管理。 ... [详细]
  • 深入解析Spring Boot自动配置机制及其核心原理
    Spring Boot 的自动配置机制是其核心特性之一,旨在简化开发过程并提高效率。本文将深入探讨这一机制的工作原理,解释其如何通过智能化的类路径扫描和条件注解实现自动装配。通过对 Spring Boot 自动配置的详细解析,读者将能够更好地理解和应用这一强大功能,从而在实际项目中更加高效地利用 Spring Boot。 ... [详细]
  • MySQL:不仅仅是数据库那么简单
    MySQL不仅是一款高效、可靠的数据库管理系统,它还具备丰富的功能和扩展性,支持多种存储引擎,适用于各种应用场景。从简单的网站开发到复杂的企业级应用,MySQL都能提供强大的数据管理和优化能力,满足不同用户的需求。其开源特性也促进了社区的活跃发展,为技术进步提供了持续动力。 ... [详细]
  • voc生成xml 代码
    目录 lxmlwindows安装 读取示例 可视化 生成示例 上面是代码,下面有调用示例 api调用代码,其实只有几行:这个生成代码也很简 ... [详细]
  • 为了深入了解某些测试框架的工作原理,并在培训中构建一个简单的测试框架,我系统地研究了 should.js 的源代码。本文将分享我的学习过程和分析结果,帮助读者更好地掌握 should.js 的核心机制。 ... [详细]
  • 如何在Android应用中设计和实现专业的启动欢迎界面(Splash Screen)
    在Android应用开发中,设计与实现一个专业的启动欢迎界面(Splash Screen)至关重要。尽管Android设计指南对使用Splash Screen的态度存在争议,但一个精心设计的启动界面不仅能提升用户体验,还能增强品牌识别度。本文将探讨如何在遵循最佳实践的同时,通过技术手段实现既美观又高效的启动欢迎界面,包括加载动画、过渡效果以及性能优化等方面。 ... [详细]
  • 在 Python 中,魔法方法 `__dict__` 和 `__getattr__` 具有重要的作用和灵活的应用。`__dict__` 是一个用于存储对象属性的字典,其中键为属性名,值为对应的属性值。通过 `__dict__`,可以动态地访问和修改对象的属性。而 `__getattr__` 方法则在尝试访问对象中不存在的属性时被调用,提供了一种优雅的处理方式,避免了属性访问错误。这两个魔法方法在实现复杂的数据结构和动态行为时尤为有用。 ... [详细]
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社区 版权所有