自動化測試環(huán)境搭建(實(shí)現(xiàn)一個(gè)iOS demo app的自動化)

參考:
1.appium
2.appium_lib
3.appium-xcuitest-driver
4.真機(jī)使用appium參考鏈接
5.WebDriverAgent

框架結(jié)構(gòu)

框架結(jié)構(gòu)

1.初始化環(huán)境

在目錄中添加init.sh(建議根據(jù)本身機(jī)器權(quán)限調(diào)整其中命令是否使用sudo執(zhí)行)和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'

執(zhí)行安裝環(huán)境腳本

bash init.sh

依賴的常用基礎(chǔ)軟件請自行搜索安裝方法,如Homebrew、Ruby、Bundler等。

環(huán)境安裝完成

2.初始化Cucumber

cucumber 傳統(tǒng)(E) 傳統(tǒng)(C)
Feature(功能) test suite 測試用例集
Scenario(情景) test case 測試用例
Given(給定) setup 創(chuàng)建測試所需環(huán)境
When(當(dāng)) test 觸發(fā)被測事件
Then(則) assert 斷言,驗(yàn)證結(jié)果

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

cucumber --init
cucumber init
初始化cucumber后的文件目錄結(jié)構(gòu)

在env.rb中配置Cucumber將使用到的庫

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

創(chuàng)建hook.rb文件和capabilities.yml文件
hook.rb會自動被Appium_lib調(diào)用,無需額外配置。hook.rb作用是使用Appium執(zhí)行模擬器配置及啟動,hook.rb從capabilities.yml文件中讀取模擬器配置和需要測試的App的路徑。(注意App路徑和capabilities.yml中路徑一致)
appium統(tǒng)一配置參數(shù)表 xcuitest框架特殊參數(shù)表

創(chuàng)建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不能重置模擬器,所以會造成數(shù)據(jù)依賴
:no_reset: false

3.添加App并編寫用例

編寫用例

在features文件夾中新建account.feature,使用Cucumber語言去實(shí)現(xiàn)Case

# language: zh-CN
功能: 我在登錄頁面"登錄"進(jìn)行登錄操作

    @e2e
    場景: 登錄
        假如 我進(jìn)入"登錄"頁面
        當(dāng) 我輸入郵箱"790032475@qq.com"和密碼"Aa1Aa11"
        并且 我點(diǎn)擊"登錄"
        并且 等待"2"秒
        那么 我應(yīng)該看到"歡迎回來"

在step_definitions文件夾中新建account.rb并實(shí)現(xiàn)對feature文件中的cucumber語句解析

實(shí)現(xiàn)cucumber語句的解析
當(dāng)(/^我進(jìn)入"([^"]*)"頁面$/) do |text|
end

當(dāng)(/^我輸入郵箱"([^"]*)"和密碼"([^"]*)"$/) do |email , password|
end

當(dāng)(/^我點(diǎn)擊"([^"]*)"$/) do |element_id|
end

當(dāng)(/^等待"([^"]*)"秒$/) do |text|
end

當(dāng)(/^我應(yīng)該看到"([^"]*)"$/) do |text|
end

在解析后的方法中,使用appium_lib和test/unit中的方法獲取元素,操作元素,并對結(jié)果進(jìn)行斷言(appium_lib的使用方式和語句參考appium_lib_ios_docs
參考附錄,如何使用WebDriverAgent查看accessibility_id從而定位元素

當(dāng)(/^我進(jìn)入"([^"]*)"頁面$/) do |text|
    assert(driver.get_source.include?(text))
end

當(dāng)(/^我輸入郵箱"([^"]*)"和密碼"([^"]*)"$/) 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

當(dāng)(/^我點(diǎn)擊"([^"]*)"$/) do |element_id|
    if element_id == "登錄"
        element_id = "loginbutton"
    end
    element = find_element accessibility_id: element_id
    element.click
end

當(dāng)(/^等待"([^"]*)"秒$/) do |text|
    sleep text.to_i
end

當(dāng)(/^我應(yīng)該看到"([^"]*)"$/) do |text|
    assert(driver.get_source.include?(text))
end

上邊的實(shí)現(xiàn)重復(fù)并且可復(fù)用性很小,需要重構(gòu)。我們新建pages文件夾,并在其中新建general_page.rb和constants.rb文件,general_page.rb是對我們實(shí)現(xiàn)邏輯的重構(gòu),constants.rb文件是對cucumber中的引號中的元素描述和 accessibility id進(jìn)行對應(yīng)的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中的實(shí)現(xiàn),使其調(diào)用general_page.rb中重構(gòu)后的方法

當(dāng)(/^我進(jìn)入"([^"]*)"頁面$/) do |text|
    GeneralPage.should_see text
end

當(dāng)(/^我輸入郵箱"([^"]*)"和密碼"([^"]*)"$/) do |email , password|
    GeneralPage.fill_element("郵箱",email)
    GeneralPage.fill_element("密碼",password)
end

當(dāng)(/^我點(diǎn)擊"([^"]*)"$/) do |element_id|
    GeneralPage.click_element element_id
end

當(dāng)(/^等待"([^"]*)"秒$/) do |text|
    GeneralPage.wait_second text
end

當(dāng)(/^我應(yīng)該看到"([^"]*)"$/) do |text|
    GeneralPage.should_see text
end

4.添加Appium啟動和Case運(yùn)行腳本

添加腳本方便Appium啟動和Case運(yùn)行

start_server.sh

appium & # start appium

run_test.sh

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

5.執(zhí)行Case,輸出Report

先使用腳本運(yùn)行Appium

bash start_server.sh

另起終端運(yùn)行腳本,執(zhí)行Case,并輸出Report

bash run_test.sh
Report
Report

附:如何使用WebDriverAgent查看現(xiàn)有app的accessibility id

clone WebDriverAgent到本地
進(jìn)入WebDriverAgent的目錄后,運(yùn)行編譯構(gòu)建WebDriverAgent

./Scripts/bootstrap.sh

使用xcodebuild運(yùn)行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

打開網(wǎng)頁http://localhost:8100/inspector

WebDriverAgent inspector
WebDriverAgent inspector
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容