使用ruby+cucumber编写测试用例

前言

前面介绍了Appium的环境配置和元素定位技巧,一些就绪后,马上开始单元测试用例的编写吧,下面手把手教你编写测试用例

下面例子全部使用Sublime Text编辑器编写

ruby语法参考

1、新建文件夹

在合适的位置创建测试目录,例子

cd Desktop
mkdir 测试用例

2、创建Gemfile文件,导入ruby依赖库

source 'https://www.rubygems.org'

gem 'appium_lib',         '~> 9.7.4'
gem 'rest-client',        '~> 2.0.2'
gem 'rspec',              '~> 3.6.0'
gem 'cucumber',           '~> 2.4.0'
gem 'rspec-expectations', '~> 3.6.0'
gem 'spec',               '~> 5.3.4'
gem 'sauce_whisk',        '~> 0.0.13'
gem 'test-unit',          '~> 2.5.5' # required for bundle exec ruby xunit_android.rb

Gem 是 Ruby 模块 (叫做 Gems) 的包管理器。其包含包信息,以及用于安装的文件。

Gem通常是依照".gemspec"文件构建的,包含了有关Gem信息的YAML文件。Ruby代码也可以直接建立Gem,这种情况下通常利用Rake来进行。

3、安装ruby依赖库

在命令行输入下面命令

bundle install

4、初始化cucumber

cucumber --init

执行上面命令,会生成如下目录结构

features # 存放feature的目录
├── step_definitions # 存放steps的目录
└── support # 环境配置
    └── env.rb

5、新建apps目录

mkdir apps

将目标.app文件拖到apps目录下,注意:这里如果使用模拟器测试,需要app文件是以模拟器架构(eg: iPhone 8)编译的,如果使用真机测试,那么app文件需要使用真机架构编译(eg: Generic iOS Device)

补充:打开工程,command+U,build完成之后,可在工程的Products目录下看到app文件

6、设置Appium服务器初始化参数

新建文件appium.txt

使用xcrun simctl list devices查看可用的设备

image.png

设置Desired Capabilities,例如

[caps]
# 模拟器
platformName = "ios"
deviceName = "iPhone 8"
platformVersion = "11.1"
app = "/Users/yangfangming/Desktop/TuanFund-Appium/apps/TuanFundApp/build/TuandaiFund.app"
automationName = "XCUITest"

参数描述

描述
automationName 自动化测试的引擎 例如 XCUITest、uiautomator2
platformName 使用的手机操作系统 例如 iOS, Android, 或者 FirefoxOS
platformVersion 手机操作系统的版本 例如 7.1, 4.4
deviceName 使用的手机或模拟器类型 例如 iPhone 8,Nexus_5X
app 本地绝对路径远程 http URL 所指向的一个安装包(.ipa,.apk,或 .zip 文件) /abs/path/to/my.apk 或 http://myapp.com/app.ipa

7、根据appium.txt配置的参数,初始化全局的driver对象

打开env.rb文件,输入如下代码

require 'rspec/expectations'
require 'appium_lib'
require 'cucumber/ast'

# Create a custom World class so we don't pollute `Object` with Appium methods
class AppiumWorld
end

# Load the desired configuration from appium.txt, create a driver then
# Add the methods to the world
caps = Appium.load_appium_txt file: File.expand_path('../appium.txt', __FILE__), verbose: true
Appium::Driver.new(caps)
Appium.promote_appium_methods AppiumWorld

World do
  AppiumWorld.new
end

Before { $driver.start_driver }
After { $driver.driver_quit }

8、新建feature文件,这里以登录为例,新建login.feature文件,输入如下代码


#language: zh-CN

功能: 账户测试

  # 作为一个开发者
  # 我已经注册了用户名为18576771524,密码为123456a的账号
  # 我希望能使用这个账号登录

  场景: 验证登录成功
    假如 广告或者引导页面存在,跳过广告和引导页面
    当   点击 "我的"
    并且 点击 "登录/注册"
    并且 在用户名输入框输入 18576771524
    并且 在密码输入框输入 123456 "a"
    并且 点击 "登录"
    并且 等待 3 秒
    那么 登录页面应该消失

创建login.feature文件后,有个小技巧,执行bundle exec cucumber运行测试用例(确保Appium服务端端已经启动),由于这里还没有创建steps,会提示如下信息

image.png

9、创建steps,根据上面的提示创建loginSteps.rb文件

最终目录结构如下

├── Gemfile # ruby依赖库
├── Gemfile.lock # 依赖库版本管理
├── apps # 目标app
│   └── TuandaiFund.app
└── features # 存放feature、steps的目录
    ├── login.feature
    ├── step_definitions # 存放steps的目录
    │   └── loginSteps.rb
    └── support # 环境配置
        ├── appium.txt
        └── env.rb

编写steps

假如(/^广告或者引导页面存在,跳过广告和引导页面$/) do
  pending # Write code here that turns the phrase above into concrete actions
end

当(/^点击 "([^"]*)"$/) do |arg1|
  pending # Write code here that turns the phrase above into concrete actions
end

当(/^在用户名输入框输入 (\d+)$/) do |arg1|
  pending # Write code here that turns the phrase above into concrete actions
end

当(/^在密码输入框输入 (\d+) "([^"]*)"$/) do |arg1, arg2|
  pending # Write code here that turns the phrase above into concrete actions
end

当(/^等待 (\d+) 秒$/) do |arg1|
  pending # Write code here that turns the phrase above into concrete actions
end

那么(/^登录页面应该消失$/) do
  pending # Write code here that turns the phrase above into concrete actions
end

编写steps可借助Appium的元素检查器appium inspector,如何启动inspector,如何定位元素和操作,前面环境配置和Appium_lib已经说过了,这里不再赘述

值得一提的是Gherkin中的关键字,假如、当、并且、那么等是等价的语法糖

假如(/^点击 "([^"]*)"$/) do
end

当(/^点击 "([^"]*)"$/) do
end

并且(/^点击 "([^"]*)"$/) do
end

上面3个steps是等价的,如果有多个当 点击 xx 按钮这样的feature,只能保留其中一个,否则运行测试用例的时候会报冲突的错误

编写完成之后的loginSteps.rb文件如下:

# 跳过广告页面
def dismiss_ad_View
  adExist = exists { id("广告页面") }
  if adExist
    sleep(5)
  end
end

# 跳过引导页面
def dismiss_guide_page
  guideExist = exists { id("引导页面") }
  # guideExist ? puts("引导页面存在") : puts("引导页面不存在")
  if guideExist
    swipe(direction: "left", element: nil)
    sleep(1)
    swipe(direction: "left", element: nil)
    sleep(1)
    button("进入首页").click
    sleep(1)
  end
end

# 跳过手势密码页面
def dismiss_gestrure_password_page
  gestureExist = exists { id("手势密码页面") }
  # guideExist ? puts("引导页面存在") : puts("引导页面不存在")
  if gestureExist
    swipe(direction: "right", element: nil)
    sleep(1)
    swipe(direction: "right", element: nil)
    sleep(1)
  end
end

假如(/^广告或者引导页面存在,跳过广告和引导页面$/) do
  dismiss_ad_View
  dismiss_guide_page
  dismiss_gestrure_password_page
end

# 按钮点击
当(/^点击 "([^"]*)"$/) do |arg1|
  e = exists { button(arg1) }
  if e 
    btn = button(arg1)
  else
    btn = driver.find_element(:id, arg1)
  end
  wait { btn.click }
end

当(/^在用户名输入框输入 (\d+)$/) do |arg1|
  textfield("请输入手机号").type arg1
end

当(/^在密码输入框输入 (\d+) "([^"]*)"$/) do |arg1, arg2|
  textfield("请输入密码").type arg1+arg2
end

# 延时执行
当(/^等待 (\d+) 秒$/) do |arg1|
  sleep(arg1.to_i)
end

那么(/^登录页面应该消失$/) do
  # 期望:登录页面dismiss
  actual = exists { id("登录页面") }
  expect(actual).to eq(false)
end

现在进入测试用例目录运行bundle exec cucumber查看测试效果吧

如果你想使用python来编写单元测试,可参考这里

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,723评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,080评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,604评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,440评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,431评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,499评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,893评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,541评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,751评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,547评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,619评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,320评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,890评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,896评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,137评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,796评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,335评论 2 342

推荐阅读更多精彩内容