自动化测试环境搭建(实现一个iOS demo app的自动化)

参考:
1.appium
2.appium_lib
3.appium-xcuitest-driver
4.真机使用appium参考链接
5.WebDriverAgent

框架结构

框架结构

1.初始化环境

在目录中添加init.sh(建议根据本身机器权限调整其中命令是否使用sudo执行)和Gemfile。

init.sh

#!/usr/bin/env bash
pwd
/bin/bash --login << EOF
rvm install ruby-2.4.0
rvm use 2.4.0
brew install node # get node.js
brew install carthage
brew install libimobiledevice --HEAD  # install from HEAD to get important updates
brew install ideviceinstaller         # only works for ios 9. for ios 10, see below
sudo npm install -g appium  # get appium
sudo npm install -g ios-deploy --allow-root --unsafe-perm=true #ideviceinstaller doesn't work with iOS 10 yet. So we need to install ios-deploy
bundle install
mkdir screenshot
EOF

Gemfile

source 'https://gems.ruby-china.org/'
gem 'cucumber'
gem 'appium_lib'
gem 'test-unit'

执行安装环境脚本

bash init.sh

依赖的常用基础软件请自行搜索安装方法,如Homebrew、Ruby、Bundler等。

环境安装完成

2.初始化Cucumber

cucumber 传统(E) 传统(C)
Feature(功能) test suite 测试用例集
Scenario(情景) test case 测试用例
Given(给定) setup 创建测试所需环境
When(当) test 触发被测事件
Then(则) assert 断言,验证结果

在工作空间中使用Cucumber初始化命令初始化

cucumber --init
cucumber init
初始化cucumber后的文件目录结构

在env.rb中配置Cucumber将使用到的库

require 'appium_lib'
require 'cucumber/ast'
require 'test/unit'

创建hook.rb文件和capabilities.yml文件
hook.rb会自动被Appium_lib调用,无需额外配置。hook.rb作用是使用Appium执行模拟器配置及启动,hook.rb从capabilities.yml文件中读取模拟器配置和需要测试的App的路径。(注意App路径和capabilities.yml中路径一致)
appium统一配置参数表 xcuitest框架特殊参数表

创建hook.rb文件和capabilities.yml文件

hook.rb

Before do
  initialise_appium
end

def load_config
  capabilities_file_path=File.dirname(__FILE__)+"/capabilities.yml"
  $APP_PATH=YAML.load_file(capabilities_file_path)[:app_path]
  $PLATFORMVERSION=YAML.load_file(capabilities_file_path)[:platform_version]
  $DEVICENAME=YAML.load_file(capabilities_file_path)[:device_name]
  $IMPLICITWAITTIME=YAML.load_file(capabilities_file_path)[:implicit_wait_time]
  $FULLRESET=YAML.load_file(capabilities_file_path)[:full_reset]
  $NORESET=YAML.load_file(capabilities_file_path)[:no_reset]
end

def load_caps
  $DESIRED_CAPS = {
      caps: {
          platformName: 'iOS',
          deviceName: $DEVICENAME,
          language: $LANGUAGE,
          locale: $LOCALE,
          app: $APP_PATH,
          platformVersion: $PLATFORMVERSION,
          fullReset: $FULLRESET,
          noReset: $NORESET
      },
      appium_lib: {
          sauce_username: nil,
          sauce_access_key: nil
      }
  }
end

def initialise_appium
  load_config
  load_caps
  @driver=Appium::Driver.new($DESIRED_CAPS)
  Appium.promote_appium_methods self.class
  @driver.start_driver.manage.timeouts.implicit_wait = $IMPLICITWAITTIME
end

def take_screenshot scenario
  screenshot_path = "./screenshot/#{scenario}.png"
  screenshot screenshot_path
end

After do |scenario|
  if scenario.failed?
    take_screenshot scenario.name
  end

  @driver.driver_quit

end

capabilities.yml

:app_path: './GossipGeek.app'
:platform_version: "10.3"
:device_name: 'iPhone 6'
:implicit_wait_time: 3 # seconds
:full_reset: false
#CI agent不能重置模拟器,所以会造成数据依赖
:no_reset: false

3.添加App并编写用例

编写用例

在features文件夹中新建account.feature,使用Cucumber语言去实现Case

# language: zh-CN
功能: 我在登录页面"登录"进行登录操作

    @e2e
    场景: 登录
        假如 我进入"登录"页面
        当 我输入邮箱"790032475@qq.com"和密码"Aa1Aa11"
        并且 我点击"登录"
        并且 等待"2"秒
        那么 我应该看到"欢迎回来"

在step_definitions文件夹中新建account.rb并实现对feature文件中的cucumber语句解析

实现cucumber语句的解析
当(/^我进入"([^"]*)"页面$/) do |text|
end

当(/^我输入邮箱"([^"]*)"和密码"([^"]*)"$/) do |email , password|
end

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

当(/^等待"([^"]*)"秒$/) do |text|
end

当(/^我应该看到"([^"]*)"$/) do |text|
end

在解析后的方法中,使用appium_lib和test/unit中的方法获取元素,操作元素,并对结果进行断言(appium_lib的使用方式和语句参考appium_lib_ios_docs
参考附录,如何使用WebDriverAgent查看accessibility_id从而定位元素

当(/^我进入"([^"]*)"页面$/) do |text|
    assert(driver.get_source.include?(text))
end

当(/^我输入邮箱"([^"]*)"和密码"([^"]*)"$/) do |email , password|
    element = find_element accessibility_id: "emailTextFiled"
    element.clear
    element.send_keys email

    element = find_element accessibility_id: "passwordTextfield"
    element.clear
    element.send_keys password
end

当(/^我点击"([^"]*)"$/) do |element_id|
    if element_id == "登录"
        element_id = "loginbutton"
    end
    element = find_element accessibility_id: element_id
    element.click
end

当(/^等待"([^"]*)"秒$/) do |text|
    sleep text.to_i
end

当(/^我应该看到"([^"]*)"$/) do |text|
    assert(driver.get_source.include?(text))
end

上边的实现重复并且可复用性很小,需要重构。我们新建pages文件夹,并在其中新建general_page.rb和constants.rb文件,general_page.rb是对我们实现逻辑的重构,constants.rb文件是对cucumber中的引号中的元素描述和 accessibility id进行对应的map。

general_page.rb

module GeneralPage
  include Test::Unit::Assertions

  def should_see text
    assert(driver.get_source.include?(text))
  end

  def load_element element_id
    Constants::ELEMENTS.include?(element_id) ? @element_id=Constants::ELEMENTS.fetch(element_id) : @element_id=element
    @element = find_element accessibility_id: @element_id
  end

  def fill_element element_id, text
    load_element element_id
    @element.clear
    @element.send_keys text
  end

  def click_element element_id
    load_element element_id
    @element.click
  end

  def wait_second text
    sleep text.to_i
  end
end

constants.rb

module Constants

  ELEMENTS={
      "注册" => "registerButton",
      "邮箱" => "emailTextFiled",
      "密码" => "passwordTextfield",
      "登录" => "loginbutton",
      "显示密码" => "passwordSwitch",
  }

end

由于我们新建的pages并不在cucumber的管理下,我们需要在evn.rb手动引用general_page.rb文件

require 'appium_lib'
require 'cucumber/ast'
require 'test/unit'

#require rb files
require File.dirname(__FILE__)+'/../pages/general_page.rb'

#include
include GeneralPage

更改account.rb中的实现,使其调用general_page.rb中重构后的方法

当(/^我进入"([^"]*)"页面$/) do |text|
    GeneralPage.should_see text
end

当(/^我输入邮箱"([^"]*)"和密码"([^"]*)"$/) do |email , password|
    GeneralPage.fill_element("邮箱",email)
    GeneralPage.fill_element("密码",password)
end

当(/^我点击"([^"]*)"$/) do |element_id|
    GeneralPage.click_element element_id
end

当(/^等待"([^"]*)"秒$/) do |text|
    GeneralPage.wait_second text
end

当(/^我应该看到"([^"]*)"$/) do |text|
    GeneralPage.should_see text
end

4.添加Appium启动和Case运行脚本

添加脚本方便Appium启动和Case运行

start_server.sh

appium & # start appium

run_test.sh

cucumber --tags=@e2e -f html -o report.html

5.执行Case,输出Report

先使用脚本运行Appium

bash start_server.sh

另起终端运行脚本,执行Case,并输出Report

bash run_test.sh
Report
Report

附:如何使用WebDriverAgent查看现有app的accessibility id

clone WebDriverAgent到本地
进入WebDriverAgent的目录后,运行编译构建WebDriverAgent

./Scripts/bootstrap.sh

使用xcodebuild运行WebDriverAgent(注意修改命令中WebDriverAgent的路径和模拟器的id)

xcodebuild build-for-testing test-without-building -project  ~/Documents/Github_Projects/WebDriverAgent/WebDriverAgent.xcodeproj -scheme WebDriverAgentRunner -destination id=50CF4B72-EEA5-40F2-8693-168A1C481E25 -configuration Debug IPHONEOS_DEPLOYMENT_TARGET=10.3

打开网页http://localhost:8100/inspector

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

推荐阅读更多精彩内容