zoukankan      html  css  js  c++  java
  • 使用calabash测试开源中国Android客户端

    Calabash-android是支持android的UI自动化测试框架,前面已经介绍过《中文Win7下成功安装calabash-android步骤》,这篇博文尝试测试一个真实应用:开源中国客户端。目的是和大家一起学习calabash测试工具。

    测试环境与源码准备

    先介绍一下oschina.net

    <www.oschina.net>

    在此输入图片描述

    oschina除了有网站,还有三大平台手机客户端:

    http://www.oschina.net/app

    客户端下载

    客户端已经开源!

    那么开源可以用来做什么呢?

    我正在学用calabash-android,得找到一个合适的待测app,平时手机上开源中国这个app用的蛮顺手了,所以就选它了,在此特别向开源中国的开发工程师致谢!

    环境准备:ADT+calabash-android

    可以参考:
    中文Win7下成功安装calabash-android步骤

    下载oschina/android-app源代码

    首先到 http://git.oschina.net/oschina/android-app

    在此输入图片描述

    以下两种下载源代码方式的方式都可以:

    1. 可以直接点击”下载zip“
    2. 复制git仓库url: https://git.oschina.net/oschina/android-app.git,然后在Eclipse/ADT中打开Windows > Open Perspective > Other... > Get Resporsitory Exploring,clone源代码

    导入到ADT中后,源代码如下:

    在此输入图片描述

    在adt-bundle-20140702中编译运行oschina/android-app的几个问题

    问题1: adt-bundle-20140702的API版本是20,所以要修改project.properties:
    target=android-15 改成 target=android-20

    问题2: 源代码是使用了已作废的class: android.webkit.CacheManager
    oschina-android-app/src/net/oschina/app/AppContext.java中使用了android.webkit.CacheManager
    所以要把相关代码禁掉:

    61行:

    //import android.webkit.CacheManager;
    

    1503到1509行:

    //		File file = CacheManager.getCacheFileBaseDir();  
    //		if (file != null && file.exists() && file.isDirectory()) {  
    //		    for (File item : file.listFiles()) {  
    //		    	item.delete();  
    //		    }  
    //		    file.delete();  
    //		}  		  
    

    问题3:Run As Android Application报错:Installation error: INSTALL_FAILED_VERSION_DOWNGRADE
    原因是:手机已经装了一个开源中国的1.7.7.0版本,而ADT要下载的是1.7.6.9版本,Android系统不允许安装一个比已安装版本更旧的版本,所以从手机上卸载已有的1.7.7.0版本就可以了。

    ADT编译并上传oschina/android-app到手机

    Run As Android Application > 选择连接到电脑Usb的手机 > OK
    在此输入图片描述

    calabash测试步骤

    先确认oschina/android-app声明了访问网络的权限

    oschina/android-app项目的AndroidManifest.xml中应该如下行:

    <uses-permission android:name="android.permission.INTERNET" />
    

    在oschina/android-app根目录中创建calabash目录

    在命令行下进入oschina/android-app的源代码根目录:

    D:gitoschina>cd android-app
    
    D:gitoschinaandroid-app>dir
     Volume Serial Number is 9823-AB19
    
     Directory of D:gitoschinaandroid-app
    
    2014/09/01  20:26    <DIR>          .
    2014/09/01  20:26    <DIR>          ..
    2014/09/01  20:21               783 .classpath
    2014/09/01  20:21    <DIR>          .git
    2014/09/01  20:21                64 .gitignore
    2014/09/01  20:21               822 .project
    2014/09/01  20:21    <DIR>          .settings
    2014/09/01  20:21            10,829 AndroidManifest.xml
    2014/09/01  20:21    <DIR>          assets
    2014/09/01  20:42    <DIR>          bin
    2014/09/01  20:26    <DIR>          gen
    2014/09/01  20:21    <DIR>          libs
    2014/09/01  20:21            18,092 LICENSE.txt
    2014/09/01  20:21             1,424 proguard.cfg
    2014/09/01  20:41               563 project.properties
    2014/09/01  20:21             4,183 README.md
    2014/09/01  20:21    <DIR>          res
    2014/09/01  20:21    <DIR>          src
                   8 File(s)         36,760 bytes
                  10 Dir(s)  133,131,993,088 bytes free
    
    D:gitoschinaandroid-app>
    

    创建calabash目录:

    D:gitoschinaandroid-app>mkdir calabash
    

    创建cucumber skeleton:

    D:gitoschinaandroid-app>cd calabash
    
    D:gitoschinaandroid-appcalabash>calabash-android gen
    
    ----------Question----------
    I'm about to create a subdirectory called features.
    features will contain all your calabash tests.
    Please hit return to confirm that's what you want.
    ---------------------------
    
    
    ----------Info----------
    features subdirectory created.
    ---------------------------
    
    D:gitoschinaandroid-appcalabash>dir
     Volume Serial Number is 9823-AB19
    
     Directory of D:gitoschinaandroid-appcalabash
    
    2014/09/01  21:54    <DIR>          .
    2014/09/01  21:54    <DIR>          ..
    2014/09/01  21:54    <DIR>          features
                   0 File(s)              0 bytes
                   3 Dir(s)  133,131,988,992 bytes free
    
    D:gitoschinaandroid-appcalabash>
    

    编辑 D:gitoschinaandroid-appcalabashfeaturesmy_first.feature:
    初始内容:

    Feature: Login feature
    
      Scenario: As a valid user I can log into my app
        When I press "Login"
        Then I see "Welcome to coolest app ever"
    

    第一行Feature: XX,第二行 Scenario: YY是给人读的,所以随便填写什么中文英文内容都可以
    关键内容是第三行When I press ..和第四行Then I see .., 这是给Cucumber软件识别的。
    When后面跟动作语句,Then后面跟内容检查语句

    先尝试如下改动:

    Feature: 启动开源中国
    
      Scenario: 启动应用后,能看到软件版本更新信息
        Then I see "软件版本更新"
    

    %windir%system32cmd.exe /k chcp65001&&ansicon 启动ansicon,
    运行calabash-andriod run
    D:gitoschinaandroid-appcalabash>calabash-android run D:gitoschinaandroid-appinoschina-android-app.apk

    在此输入图片描述
    测试失败,原因是Then的默认等待时间只有2秒,开源中国app的启动时间比较长。
    ansicon中未能显示中文:"软件版本更新",这个后面补充中有描述。

    按照 https://github.com/calabash/calabash-android/blob/master/ruby-gem/lib/calabash-android/canned_steps.md的指导,可以指定等待几秒:

    Feature: 启动开源中国
    
      Scenario: 启动应用后,能看到软件版本更新信息
      	Then I wait for 10 seconds
    	Then I see "软件版本更新"
    

    在此输入图片描述

    手机上看到的开源中国启动后画面:

    在此输入图片描述

    按钮“立即更新”为什么是红色的?以后再解决。

    到此步为止,calabash测试开源中国Android客户端的环境已经建立完毕,接下去同学们就可以欢快的尝试canned_steps.md里的各个预定义步骤了。

    我也会继续完成这个测试用例,大家一起共同进步!

    补充解决问题:calabash测试输出中不能显示中文

    解决方法:
    ansicon启动时,不要用chcp 65001设置为UTF-8编码,
    %windir%system32cmd.exe /k ansicon 启动ansicon,然后运行calabash:

    在此输入图片描述

    试用calabash预定义指令

    试用 press, don't see, screenshot

    运行前,先把D:gitoschinaandroid-appcalabash下的screenshot_*.png都删了,避免搞不清楚旧图和新图。

    不解释,看脚本和截图:

    Feature: 启动开源中国
    
      Scenario: 启动应用后,能看到软件版本更新信息
        Then I wait for 5 seconds
        Then I take a screenshot
        Then I see "软件版本更新"
        Then I see "以后再说"
        When I press "以后再说"
        Then I don't see "以后再说"
        Then I take a screenshot
    

    在此输入图片描述

    在此输入图片描述

    calabash脚本生成的手机截图:

    在此输入图片描述

    在此输入图片描述

    到系统设置中启用左右滑动,为了后面测试手势指令

    Feature: 启动开源中国
    
      Scenario: 启动应用后,能看到软件版本更新信息
        Then I wait for 5 seconds
        Then I see "软件版本更新"
        Then I see "以后再说"
        Then I take a screenshot
        When I press "以后再说"
        Then I don't see "以后再说"
        Then I see "最新资讯"
        Then I take a screenshot
        Then I press the menu key
        Then I see "系统设置"
        Then I take a screenshot
        When I press "系统设置"
        Then I see "已关闭左右滑动"
        Then I take a screenshot
        When I press "已关闭左右滑动"
        Then I see "已启用左右滑动"
        Then I take a screenshot
        Then I go back
        Then I see "最新资讯"
        Then I take a screenshot
    

    在此输入图片描述

    在此输入图片描述

    在此输入图片描述

    手势:swipe right = 翻看右边的内容

    这个right比较难理解,是不是解释为“翻看右边的内容”比较容易记住。
    Feature: 启动开源中国
    ...
    Then I swipe right
    Then I see "问答"
    Then I don't see "最新资讯"
    Then I take a screenshot

    在此输入图片描述

    在此输入图片描述

    scroll up 运行失败

          Then I scroll up
    

    在此输入图片描述

    找不到android.widget.ScrollView元素,看样子oschina的可滚动区域不是用标准控件实现的。

    通过id找到控件并做相应操作

    接下去我要搜索包含"calabash"的博客,

    首先要点击首页右上角的放大镜图标:

    放大镜图标

    这个图标上没有text可以识别,所以必须到首页布局文件mail.xml中找到搜索图标的id,

    ADT中打开文件:D:gitoschinaandroid-app eslayoutmain.xml

    main.xml

    点击搜索图标,右上角的Outline指示搜索图标在main_header.xml中定义。

    双击 include-main_header,ADT打开main_header.xml:

    search-id

    点击搜索图标,右边的Outline和Properties区都指示搜索图标的id是main_head_search,控件类型是:ImageButton

    接下去在calabash中可以用id点击搜索图标了:

      Feature: 搜索包含calabash的博客
      
        Scenario: 启动应用后,能搜到包含calabash的博客
          Then I wait for 5 seconds
          Then I see "软件版本更新"
          Then I see "以后再说"
          Then I take a screenshot
          When I press "以后再说"
          Then I don't see "以后再说"
          Then I see "最新资讯"
          Then I take a screenshot
          When I press view with id "main_head_search"
          Then I see "软件"
          Then I see "问答"
          Then I see "博客"
          Then I see "新闻"
          Then I take a screenshot
    

    with-id

    搜索输入框

    我尝试了把I press view with id "main_head_search" 改成 I press "main_head_search",也能找到该搜索图标。
    说明:I press "test/id" 是万能语法,同时支持文本和id定位控件。那我就不用再记住复杂语句I press view with id "main_head_search"了。

    no-with-id

    输入文本并按回车键搜索

      Feature: 搜索包含calabash的博客
          ...
          When I enter "calabash测试" into input field number 1
          Then I take a screenshot
          When I press the enter button
          Then I see "已加载全部"
          Then I take a screenshot
    

    calabash-index-enter

    输入calabash测试

    这里的enter button 就是软键盘上的"搜索"键。

    搜索calabash结果

    注意: 用index查找控件,是从1开始的,而不是像C/Java数组的元素下标那样从0开始。

    为了验证index从1开始,下面再尝试登录

      Feature: 登录开源中国
      
        Scenario: 启动应用后,输入账号和密码能登录开源中国
          Then I wait for 5 seconds
          Then I see "软件版本更新"
          Then I see "以后再说"
          Then I take a screenshot
          When I press "以后再说"
          Then I don't see "以后再说"
          Then I see "最新资讯"
          Then I take a screenshot
          Then I press the menu key
          Then I see "用户登录"
          Then I take a screenshot
          When I press "用户登录"
          Then I see "记住我的登录信息"
          Then I take a screenshot
          When I enter "username" into input field number 1
          And I enter "123456" into input field number 2
          And I press button number 2 
          Then I see "登录失败用户名或口令错"
          Then I take a screenshot
    

    calabash-login

    在此输入图片描述

    在此输入图片描述

    说明:

    1. 登录窗口中,有两个输入框:"账号"和"密码",index分别是1和2
    2. 登录窗口中,有两个button:"记住我的登录信息"和"登录",index分别是1和2,checkbox也是button,奇怪吧?
    3. 尝试I press "登录"定位登录按钮失败

    calabash测试集管理

    一个Feature下包含多个Scenario

    D:gitoschinaandroid-appcalabashfeaturesfirst.feature 改名为 startup.feature,内容如下:

    Feature: 启动开源中国
    
      Scenario: 首次启动应用后,启用左右滑动
        When I wait up to 5 seconds to see "软件版本更新"
        Then I see "以后再说"
        Then I take a screenshot
        When I press "以后再说"
        Then I don't see "以后再说"
        Then I see "最新资讯"
        Then I take a screenshot
        Then I press the menu key
        Then I see "系统设置"
        Then I take a screenshot
        When I press "系统设置"
        Then I see "已关闭左右滑动"
        And  I see "启动检查更新"
        Then I take a screenshot
        When I press "已关闭左右滑动"
        Then I see "已启用左右滑动"
        When I press "启动检查更新"
        Then I take a screenshot
        
      Scenario: 第二次启动应用后,往右滑动到"问答"
        When I wait up to 5 seconds to see "最新资讯"
        When I swipe right
        Then I see "问答"
        Then I take a screenshot      
    

    本Feature有两个Scenario:

    • 第一个在系统设置中启用左右滑动,关闭启动时检查更新
    • 第二个往右滑动到“问答”页

    需要说明的是:

    • 每个Feature在运行前都会退出app,卸载app,重装app,启动app
    • 每个Scenario在运行前都会退出app,启动app
    • I see "启动检查更新" 只有在1280x720分辨率的手机上才能看到;854x480的手机上看不到,会运行错误。

    一次运行多个Feature文件

    按照 http://www.cnblogs.com/puresoul/archive/2011/12/28/2305160.html 的《Cucumber入门之Gherkin》介绍,

    一旦我们写好了一个feature文件,我们就可以使用 cucumber命令来运行它。如果cucumber命令后不跟任何东西的话,那么它会执行所有的.feature文件。如果我们只想运行某一个.feature文件,我们可以使用命令cucumber featuresfeature_name

    我现在在目录D:gitoschinaandroid-appcalabashfeatures下有两个feature文件:

    D:gitoschinaandroid-appcalabash>dir features*.feature
     驱动器 D 中的卷是 工作
     卷的序列号是 9823-AB19
    
     D:gitoschinaandroid-appcalabashfeatures 的目录
    
    2014/09/14  21:17               775 login.feature
    2014/09/15  21:20               932 startup.feature
                   2 个文件          1,707 字节
                   0 个目录 131,744,169,984 可用字节
    

    login.feature 和 startup.feature,feature的执行顺序无关紧要,因为每个feature运行时都要重新安装一遍app。

    D:gitoschinaandroid-appcalabash>calabash-android run ..inoschina-android-app.apk
    

    将执行这两个feature文件。

    如果只想执行 startup.feature 文件,要在calabash-android命令后面添加 featuresstartup.feature

    D:gitoschinaandroid-appcalabash>calabash-android run ..inoschina-android-app.apk featuresstartup.feature
    

    中文Win7环境特别说明:
    如果feature文件名是中文的,比如:启动.feature,那么在cmd 中 chcp 65001 后,运行命令:

    D:gitoschinaandroid-appcalabash>calabash-android run ..inoschina-android-app.apk features启动.feature
    

    将报错:

    invalid byte sequence in UTF-8 (ArgumentError)
    

    中文Win7下中文编码统计:

    • 文件名:GBK
    • feature文件内容:UTF-8
    • cmd:首次测试app或换手机后,UTF-8,feature中的中文显示为空白
    • cmd:第二次测试app,GBK,feature中的中文能正确显示

    Ubuntu环境下,feature文件名包含中文没有任何问题。

    我们看一下calabash-android的命令参数格式:

    D:gitoschinaandroid-appcalabash>calabash-android
      Usage: calabash-android <command-name> [parameters] [options]
      <command-name> can be one of
        help
          prints more detailed help information.
        gen
          generate a features folder structure.
        setup
          sets up a non-default keystore to use with this test project.
        resign <apk>
          resigns the app with the currently configured keystore.
        build <apk>
          builds the test server that will be used when testing the app.
        run <apk>
          runs Cucumber in the current folder with the enviroment needed.
        version
          prints the gem version
    
      <options> can be
        -v, --verbose
          Turns on verbose logging
    

    我猜想其中的[parameters]就是指cucumber参数

    扩展calabash预定义指令

    从环境变量读取测试数据

    有一个现实的需求:
    如果有一个oschina测试帐号要在多个Feature中使用,
    或者我的calabash测试脚本共享给其他人后,他的oschina测试帐号要换成自己的。
    如果直接修改Feature文件中的账号和密码,可能要修改多个地方。
    所以,设想是否能扩展calabash预定义指令:

    Then /^I enter "([^"]*)" into input field number (d+)$/ do |text, index|
    

    扩展为支持从环境变量读取输入文本:

    Then /^I enter $([^$]*) into input field number (d+)$/ do |text_ev, index|
    

    从文件 D: uby-1.9.3-p545-i386-mingw32lib ubygems1.9.1gemscalabash-android-0.5.1libcalabash-androidstepsenter_text_steps.rb 中拷贝:

    Then /^I enter "([^"]*)" into input field number (d+)$/ do |text, index|
      enter_text("android.widget.EditText index:#{index.to_i-1}", text)
    end
    

    D:gitoschinaandroid-appcalabashfeaturesstep_definitionscalabash_steps.rb 中,改动后,如下:

    require 'calabash-android/calabash_steps'
    
    Then /^I enter %([^%]*)% into input field number (d+)$/ do |text_ev, index|
      text = ENV[text_ev]
      enter_text("android.widget.EditText index:#{index.to_i-1}", text)
    end
    
    Then /^I enter $([^$]*) into input field number (d+)$/ do |text_ev, index|
      text = ENV[text_ev]
      enter_text("android.widget.EditText index:#{index.to_i-1}", text)
    end
    

    这里环境变量支持两种格式:

    • %test_ev% Windows cmd的格式
    • $test_ev Linux Bash的格式

    然后运行calabash前,设置环境变量:

    D:gitoschinaandroid-appcalabash>set td_username_1=username1
    D:gitoschinaandroid-appcalabash>set td_password_1=123456
    

    上述两条命令也可以放到 testdata.bat 文件中,然后执行testdata.bat:

    set td_username_1=username1
    set td_password_1=123456
    

    修改 login.feature :

    Feature: 登录开源中国
    
      Scenario: 启动应用后,输入错误的账号和密码不能登录
        Then I wait for 5 seconds
        Then I see "软件版本更新"
        Then I see "以后再说"
        Then I take a screenshot
        When I press "以后再说"
        Then I don't see "以后再说"
        Then I see "最新资讯"
        Then I take a screenshot
        Then I press the menu key
        Then I see "用户登录"
        Then I take a screenshot
        When I press "用户登录"
        Then I see "记住我的登录信息"
        Then I take a screenshot
        When I enter %td_username_1% into input field number 1
        And I enter $td_password_1 into input field number 2
        And I press button number 2 
        Then I see "登录失败用户名或口令错"
        Then I take a screenshot
    

    运行calabash:

    D:gitoschinaandroid-appcalabash>calabash-android run ..inoschina-android-app.apk featureslogin.feature
    

    在此输入图片描述

    为了支持跨平台测试数据维护,可以把环境变量设置放入ruby脚本 testdata.rb 中:

    ENV["td_username_1"]="username1"
    ENV["td_password_1"]="123456"
    

    在irb中运行calabash:

    D:gitoschinaandroid-appcalabash>irb
    irb(main):001:0> require './testdata.rb'
    => true
    irb(main):002:0> ENV["td_username_1"]
    => "username1"
    irb(main):003:0>exec('calabash-android run ..inoschina-android-app.apk featureslogin.feature')
    

    Ruby设置和读取环境变量真是太方便了,执行系统命令也很方便,不需要到处import库,值得深入掌握。

    Linux补充:

    Linux下可以把测试数据写入testdata.bashrc 中:

    export td_username_1="username1"
    export td_password_1="123456"
    

    enter_text_steps.rb 文件位置:

    /var/lib/gems/1.9.1/gems/calabash-android-0.5.2/lib/calabash-android/steps/enter_text_steps.rb
    

    ruby控制台下使用query查询app当前页面的控件

    参考文档:
    https://github.com/calabash/calabash-android/wiki/05-Query-Syntax
    http://blog.lesspainful.com/2012/12/18/Android-Query/

    按照上述文档很容易查询控件的id, 比如启动开源中国后的首页,查询结果:

    D:gitoschinaandroid-appcalabash>calabash-android console ..inoschina-android-app.apk
    irb(main):001:0> reinstall_apps
    5168 KB/s (2498389 bytes in 0.472s)
    3800 KB/s (544875 bytes in 0.140s)
    nil
    irb(main):002:0> start_test_server_in_background
    nil
    

    启动后首页弹出升级提示对话框:

    在此输入图片描述

    irb(main):003:0> query('button')
    

    在此输入图片描述

    看出问题没有,中文编码问题又来捣乱了:

    "text" => "u7ACBu5373u66F4u65B0", 的中文是"立即更新",这里只能看的是4个中文字
    "text" => "u4EE5u540Eu518Du8BF4", 的中文是"以后再说"

    又要说人家Ubuntu了,Ubuntu下query结果的中文能直接显示。

    在console下还可以点击按钮,
    https://github.com/calabash/calabash-android/blob/master/ruby-gem/lib/calabash-android/steps/press_button_steps.rb 中定义了按button编号点击的指令 :

    Then /^I press button number (d+)$/ do |index|
      tap_when_element_exists("android.widget.Button index:#{index.to_i-1}")
    end
    

    要选择按钮"以后再说",把 #{index.to_i-1} 代成1, 在console下输入:

    tap_when_element_exists("android.widget.Button index:1")
    

    然后按钮"以后再说"被点击,升级提示对话框消失了:

    在此输入图片描述

    所以,可以放心的在feature文件中加入指令:

    Then I press button number 2
    

    下面还希望找到右上角搜索图标的id,在console下输入:

    query("*")
    

    总共列出了111个控件,编号从0到110,其中第7个是:

    irb(main):008:0> query("*")
    [
        ...
        [  7] {
                            "id" => "main_head_search",
                       "enabled" => true,
            "contentDescription" => nil,
                         "class" => "android.widget.ImageButton",
                          "rect" => {
                "center_y" => 90,
                "center_x" => 676,
                  "height" => 80,
                       "y" => 50,
                   "width" => 80,
                       "x" => 636
            },
        ...
    ]
    

    根据其坐标(x,y) = (636,50),可以确定就是右上角的搜索按钮,按钮的id是main_head_search。

    还可以查询本页面的button:

     query("imagebutton")
    

    只有1个查询结果,就是搜索按钮:

    irb(main):008:0> query("imagebutton")
    [
        [0] {
                            "id" => "main_head_search",
                       "enabled" => true,
            "contentDescription" => nil,
                         "class" => "android.widget.ImageButton",
                          "rect" => {
                "center_y" => 90,
                "center_x" => 676,
                  "height" => 80,
                       "y" => 50,
                   "width" => 80,
                       "x" => 636
            },
                           "tag" => nil,
                   "description" => "android.widget.ImageButton{42a889a0 VFED..C. ..
    ...... 636,0-716,80 #7f0b00a3 app:id/main_head_search}"
        }
    ]
    

    接下来可以用两者方式点击搜索按钮,
    第一种,对应指令是 Then I press image button number 1

    tap_when_element_exists("android.widget.ImageButton index:0")
    

    第二种,对应指令是 Then I press "main_head_search"

    tap_when_element_exists("* marked:'main_head_search'")
    
  • 相关阅读:
    学英语+运动
    污染的城市
    初识 Microsoft Word
    拿到我人生中的第一张信用卡
    Advanced SharePoint Services Solutions
    DBCC DBREINDEX重建索引提高SQL Server性能【转载】
    Web cast: SharePoint Portal Server Web Part开发 [Resource]
    What's new on site Web Part for SPS [Free]
    Building Web Parts for SPS读书笔记(1)
    SharePoint Products and Technologies 2003 Software Development Kit (SDK)
  • 原文地址:https://www.cnblogs.com/fitnessefan/p/3950449.html
Copyright © 2011-2022 走看看