转载请注明出处:https://lizhaoxuan.github.io
前言
上一篇我们讲了Calabash的基本用法,有了上一篇的经验,已经可以写基本的测试脚本了,只不过一些特殊情况会写的不那么方便,这一篇我们讲一些Calabash的进阶用法:大概是这几个方向:
- 在自定义的Steps中使用Query语句。
- 自定义Steps支持环境变量扩展。
- Hooks。
- Calabash源码修改与扩展。
在自定义的Steps中使用Query语句
上一篇我们简单介绍了Query的用法和通过Query来帮助我们编写测试脚本。
但这个是建立在人工查询结果上,如果可以让脚本自己去查,是不是会更便捷?
Calabash提供的预定义Steps中,只有极个别几种View的Steps,类似ImageView等控件暂时还没有这种待遇,按照一般情况,我们只能选择通过ID,或者人工Query查询ImageView的index。那么如果可以只通过肉眼判断当前ImageView的index就可以编写脚本是不更好呢?
我们来自定义一个Step:
1 | When /^I press imageView number (\d+)$/ do |index| |
为了保证Steps的自然语义,这里我们也对index做了减1操作。
你也看到了,在Steps的定义体中,是可以使用Query语句的,不过这样的写法稍显繁琐了
1 | When /^I press imageView number (\d+)$/ do |index| |
tap_when_element_exists
本身也支持一定程度的查询功能。
你可能会问了,既然这些库方法已经支持这样的查询了,在内部写Query语句看起来也没啥用了啊。下面我们把Calabash预定义的Steps源码拿来瞅瞅你就知道用处在哪里了:
1 | Then /^I select "([^\"]*)" from "([^\"]*)"$/ do |item_identifier, spinner_identifier| |
解释一下:首先查询是否有对应描述的下拉列表控件,查询的结果是一个数组,如果结果是空的,那么就调用点击事件尝试点击一下,不出意外会报错找不到这个控件。
如果不是空的,那就点击这个查询结果的第零个元素。touch
方法,如果传递的参数是一个数组,会默认点击第零个元素。
然后点击弹出的PopupWindow中的item。
自定义Steps支持环境变量扩展
有几个场景。
- 如果测试不同的系统或者不同分辨率的手机,测试用例内部可能需要细微改变,为了应对这些改变,复制多套脚本进行修改显然不是特别合适。
- 不同账号有不同的权限和数据,同一个测试用例可能需要不同的账号来测试,为了应对不同账号复制多套脚本进行修改显示不是特别合适。
- 初期想要让android和iOS无缝的使用一套脚本不太现实,两套脚本几乎必然,但如果遇到上面的现象,测试中需要使用一套数据进行支持(账号),这个时候两边都维护一套一模一样的数据就不太合适了。
以上场景的解决实质是,如何在不修改脚本的情况下,可以改变其中的参数?
其解决方案便是:引入环境变量。
新建一个新的自定义Step:
1 | Then /^I enter \$([^\$]*) into input field number (\d+)$/ do |text_ev, index| |
有两处改变,方法名中的参数接收处:\$([^\$]*)
和方法体中的参数获取:text = ENV[text_ev]
这里基本照猫画虎就好了。
feature中这样调用:
1 | Then I enter $env_account_1 into input field number 1 |
$
后面的变量名是环境变量名。
在执行calabash-android run **.apk
前先设置环境变量
1 | set env_account_1 123456 |
这样,在脚本执行过程中,会将123456当做账号填写到输入框中。
但这只是最基础的用法,当需要的环境变量非常多时,再使用这样的方式明显不太合适,这个时候可以将之放入ruby脚本中,也便于维护。
新建test_data1.rb1
2ENV["env_account_1"]="1111111111"
ENV["env_password_1"]="123456"
新建test_data2.rb1
2ENV["env_account_1"]="222222222"
ENV["env_password_1"]="123456"
终端中执行如下命令
1 | Crowdsource-android git:(feature/testing) ✗ irb |
这样就可以整套整套的替换环境变量进行测试,ENV["env_account_2"]
命令用来查看环境变量的值。
Hooks
关于Hooks,我们在前面第二章有简单提过一下。Hooks就是在监听程序运行的某个阶段,并做一些事情。在feature/support文件夹下有三个关于Hooks的文件:app_installation_hooks.rb , app_life_cycle_hooks.rb , hooks.rb
前两个文件分别是对app安装的Hooks,和app生命周期的Hooks。hooks.rb文件夹是空的,由我们自己来编写。
这里暂时还没有做过什么特别的实践,我偷个懒,直接将 立成 @richardcao博客中的关于这一部分的段落摘了过来,原文在这里:http://richardcao.me/2016/10/31/客户端自动化测试小探索/。
1 | 我们看一个简单的app_life_cycle_hooks.rb理解理解: |
Calabash源码修改与扩展
前面我们提到了两种自定义Calabash Steps的方法,分别是自定义Steps和封装已有的Steps。还有第三种更为深入的定制化方案,那就是修改Calabash源码自定义Actions,这里的Actions指的便是我们之前经常会看到的,类似这样的代码: perform_action('swipe', 'right') perform_action('tap_map_marker_by_title', marker_title, 60000)
其中swipe,tap_map_marker_by_title实际是方法名,他们的核心,以Calabash-android为例,实际也是Android工程 java代码实现的。如果你有看过其他关于Calabash-android的博客,会有介绍修改其源码,创建自定义的Actions方法的实例。
基本原理是:Calabash目录/calabash-android/ruby-gem/test-server/instrumentation-backend
是一个Android工程,在其包/src/sh/calaba/instrumentationbackend/actions
中实现了我们用到的ruby库方法。
在其中创建我们自己的Action类,然后进行编译,即可创建我们自己的库方法并使用。
但这样的博客都写于2016年之前,目前最新的Calabash-android项目的源码已经删除了/calabash-android/ruby-gem/test-server
目录下的文件夹,通过翻阅Git记录得知:Calabash-android在2015.12.12日删除了本地的test_server目录,将其移动到了新的项目:calabash-android-server中。如果你将Calabash-android项目切换到2016年之前,还可以找到test_server目录,查看里面的Android工程,修改并重新编译。但我并不建议你这样去做,使用这种方式扩展意味着要放弃 Calabash一年以上的更新进度。
calabash-android-server同样是开源项目,虽然暂时我还没搞明白如何在这个项目中修改源码并应用到Calabash-android中,但只是单纯研究其源码还是非常有价值的!
我挑了其中最简单的一个类,我们来研究一下:
../actions/gestures/ClickOnScreen.java
1 | package sh.calaba.instrumentationbackend.actions.gestures; |
先看下Steps的定义中是怎么用这个方法的:1
2
3Then /^I click on screen (\d+)% from the left and (\d+)% from the top$/ do |x, y|
perform_action('click_on_screen', x, y)
end
public String key()
方法便是定义Action方法的名称。public Result execute(String... args)
便是实现。
Result返回值表示该动作是否执行成功。如果失败,会直接抛到终端中进行显示错误信息。
这里我们重点关注这个对象:InstrumentationBackend.solo
获取界面信息,以及真正实现点击操作的,都是通过solo对象来实现的。那么这个solo对象是个啥?
我们摘取InstrumentationBackend
类的一段代码:
1 | ... |
solo实际是com.jayway.android.robotium.solo.SoloEnhanced类。看到这里应该明白了,Calabash-android对UI的操作核心其实借助以Robotium来做的。
Robotium是一款国外的Android自动化测试框架,主要针对Android平台的应用进行黑盒自动化测试,它提供了模拟各种手势操作(点击、长按、滑动等)、查找和断言机制的API,能够对各种控件进行操作
哦,还要提一点,Calabash不支持跨进程的原有就在于Robotium不支持跨进程,所以让Calabash支持跨进程的契机就在这里,修改其源码,调用uiautomator的API即可,具体可行性和方式还待探索,如果你有兴趣,不妨我们一起研究呀
总结
OK,大概就是这样了,Calabash进阶部分会随时更新,修改Calabash-android-server源码进行扩展的方法我也会继续研究下去,成功以后会随时更新博客。
《Calabash探索3-Calabash进阶》