自动化测试Appium

使用ruby+cucumber编写测试用例

2018-07-31  本文已影响335人  kawa007

前言

前面介绍了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来编写单元测试,可参考这里

上一篇下一篇

猜你喜欢

热点阅读