Appium入門指南 - 環境搭建和Case編寫
本文件將詳細介紹如何搭建 Appium 的執行環境,以及如何編寫一個簡單的 UI 自動化測試用例。其中,也會穿插講解一些 Appium 的基本知識。關於 Appium 的更多資訊,大家可以檢視官方文件。
注意事項:
- 本文件是在 macOS 系統的基礎上講解相關操作
- 程式語言選擇了:Python 2.7
- Appium 是跨平臺的 UI 自動化測試框架,支援 Android、iOS 等系統,本次只介紹基於 Android 的自動化測試
安裝 Appium
Appium 的安裝有兩種方式:
1、下載 Appium Desktop,這個是 Appium 的客戶端軟體,包含了執行 Appium 所需要的一切,下載後安裝即可,支援 Mac、Windows、Linux 三大系統。因為安裝過程實在是太簡單了,所以不做詳細說明。
命令列安裝
以下命令都是在終端(Terminal)上執行的
1、安裝包管理工具 Homebrew
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
2、安裝 Node.js
brew install node
3、安裝 Appium 服務端
npm install -g appium
4、安裝 appium-doctor
npm install -g appium-doctor
5、執行 appium-doctor,檢查 Appium 需要的所有依賴是否都滿足
appium-doctor --android
其中有幾個依賴項是必須要滿足的:
- Node.js
- ANDROID_HOME
- JAVA_HOME
- adb
- android
- emulator
- $JAVA_HOME/bin
大家可根據這個命令執行結束後的提示資訊去完成相應的依賴新增:
6、安裝 Appium 客戶端
pip install Appium-Python-Client
7、最後,因為需要使用 Python 語言編寫自動化測試用例,建議安裝 Python 語言的 IDE:PyCharm
指令碼編寫
指令碼編寫前的準備工作
1、啟動 Appium
(1)如果安裝了 Appium Desktop,可直接開啟軟體點選 "Start" 啟動 Appium 服務
(2)如果是通過命令列方式安裝的 Appium,則在終端(Terminal)輸入:
appium
2、啟動模擬器/測試裝置連線至電腦
#啟動模擬器
emulator @<emulator_name>
#測試裝置連線至電腦
(1)Settings-Developer options-USB debugging //開啟usb除錯模式
(2)adb devices //檢視手機是否成功連線至電腦
3、安裝待測應用到模擬器/測試裝置中
adb install <path_to_apk>
本次講解計算器應用 iClever Calculator Lite 為例,可自行到 Google Play 上下載該應用,包名為:weightloss.constellation.education.tools
建立指令碼
在完成以上三步後,開啟 Pycharm 或者其他 IDE,新建一個 py 檔案,完成自動化測試指令碼基礎程式碼的編寫。
1、新建 calculator_test.py 檔案
2、匯入類庫和包
#匯入unittest測試框架
import unittest
#匯入appium客戶端庫
from appium import webdriver
#匯入time模組
from time import sleep
3、建立一個類 CalculatorTest,繼承自 Python 的測試類 unittest.TestCase
class CalculatorTest(unittest.TestCase):
pass
unittest 是 Python 的一個單元測試框架,包含了四個部分:
- TestFixture
- setUp
- TestCase
- TearDown
- TestCase
- TestSuite
- TestRunner
關於各部分的概念和應用,在下面章節裡說明(參見程式碼註釋)。
4、在類中建立三個方法:setUP()、tearDown()、test_case_1(),然後在類外面建立一個程式入口
class CalculatorTest(unittest.TestCase):
# pass
#SetUP,case執行前的環境初始化
def setUp(self):
pass
#TearDown,case執行後的環境恢復
def tearDown(self):
pass
#TestCase,測試用例1
def test_case_1(self):
pass
#程式入口
if __name__ == '__main__':
#TestSuite,將所有測試用例載入suite
suite = unittest.TestLoader().loadTestsFromTestCase(CalculatorTest)
#TestRunner,執行測試用例
unittest.TextTestRunner(verbosity=2).run(suite)
5、在 setUP() 中新增字典變數 desired_caps,初始化配置,提供建立 Session 所需要的資訊
#SetUP,case執行前的環境初始化
def setUp(self):
# pass
#字典變數,初始化配置,提供建立session的所有必要資訊:http://appium.io/docs/en/writing-running-appium/caps/index.html
desired_caps = {}
#被測應用平臺:iOS/Android
desired_caps['platformName'] = 'Android'
#被測應用平臺版本:adb shell getprop ro.build.version.release
desired_caps['platformVersion'] = '8.0.0'
#測試裝置名:adb devices
desired_caps['deviceName'] = 'CB512FCM14'
#被測應用包名
desired_caps['appPackage'] = 'weightloss.constellation.education.tools'
#被測應用啟動時的活動名
desired_caps['appActivity'] = 'com.weightloss.constellation.education.tools.SplashActivityAlias'
#服務端等待客戶端傳送訊息的超時時間
desired_caps['newCommandTimeout'] = 150
#在一個session開始前不重置被測程式的狀態
desired_caps['noReset'] = True
#是否支援uicode的鍵盤(輸入中文需設定)
desired_caps['unicodeKeyboard'] = True
#以desired_caps作為引數初始化WebDriver連線
#Appium伺服器的IP:http://localhost
#埠號:4723
self.driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)
sleep(10)
其中,有兩個變數 "platformVersion" 和 "deviceName" 需要大家自行修改,可通過以下命令獲取測試裝置系統版本號和裝置名
adb shell getprop ro.build.version.release //獲取測試裝置系統版本號
adb devices //獲取裝置名
6、在 tearDown() 中呼叫 quit(),退出driver,關閉被測應用所有的關聯視窗
#TearDown,case執行後的環境恢復
def tearDown(self):
# pass
#退出driver,關閉被測應用所有的關聯視窗
self.driver.quit()
7、至此,一個基礎的 Appium 自動化測試指令碼已編寫完成。通過終端(Terminal)進入指令碼所在的目錄,輸入以下語句執行指令碼
python calculator_test.py
自動化測試用例的編寫
在完成上述步驟後,一個基礎的自動化測試指令碼便生成了。接下來,具體講解如何編寫 case。
case 的編寫,簡而言之有三步:
- 1.動作執行
- 查詢和識別元素
- 操作元素
- 2.結果判斷
- 3.報告展示
動作執行
查詢和識別元素
元素,在這裡指的是應用程式使用者介面上的控制元件。可以通過谷歌官方提供的工具 uiautomatorviewer 進行查詢和識別。
1、進入 Android SDK 的 bin 目錄
cd ${ANDROID_HOME}/tools/bin //每個人的Android sdk的目錄名不一樣哦
2、啟動 uiautomatorviewer
uiautomatorviewer
3、在測試裝置上啟動應用,進入需要識別和操作的使用者介面。在 uiautomatorviewer 上,點選左上角第二個按鈕"Device Screenshot(uiautomator dump)",對當前介面上的元素進行查詢和識別
4、在獲取到介面上元素的佈局層級及其屬性後,可以通過如下一些方法進行元素的識別
- find_element_by_id---對應元件屬性中的"resource_id"
- find_element_by_class_name---對應元件屬性中的"class"
- find_element_by_name---對應元件屬性中的"text"
- find_element_by_accessibility_id---對應元件屬性中的"content-desc"
更多方法,請檢視 Appium 的官方文件
http://appium.io/docs/en/writing-running-appium/finding-elements/
http://appium.io/docs/en/commands/element/find-elements/index.html#selector-strategies
https://github.com/SeleniumHQ/mobile-spec/blob/master/spec-draft.md
http://appium.io/docs/en/writing-running-appium/android/uiautomator-uiselector/index.html
操作元素
元素操作的方法,分為三種:
- 獲取控制元件的資訊
- text(self)---獲取文字資訊
- click(self)---點選
- clear(self)---清空文字
- is_enabled(self)---是否可用
- is_selected(self)---是否已選
- is_displayed(self)---是否顯示
- send_keys(self, *value)---模擬輸入文字
- 手勢操作
- tap(self, positions, duration=None)---點選,自定義座標
- swipe(self, start_x, start_y, end_x, end_y, duration=None)---滑動
- flick(self, start_x, start_y, end_x, end_y)---快速滑動
- pinch(self, element=None, percent=200, steps=50)---縮小
- zoom(self, element=None, percent=200, steps=50)---放大
- scroll(self, origin_el, destination_el)---滾動
- drag_and_drop(self, origin_el, destination_el)---拖曳
- 系統操作
- press_keycode()---模擬按鍵
- long_press_keycode()---模擬長按鍵
- reset()---重置程式到初始狀態
- pull_file()---從手機上拉取檔案
- launch_app()---啟動應用程式
- start_activity()---啟動活動
- shake()---晃動手機
- get_screenshot_as_file()---獲取截圖並儲存在電腦上
- push_file()---推送檔案到手機
更多操作元素的方法,請檢視 Appium 的官方文件
本次例項,以 iClever Calculator Lite 為被測應用,建立一個 test_plus() 方法,查詢和識別以及操作元素
def test_plus(self):
#預期結果等於10
result = 10
#通過ID找到7
seven = self.driver.find_element_by_id("weightloss.constellation.education.tools:id/button_7")
#通過ID找到3
three = self.driver.find_element_by_id("weightloss.constellation.education.tools:id/button_3")
#通過ID找到+
plus = self.driver.find_element_by_id("weightloss.constellation.education.tools:id/button_plus")
#通過ID找到=
equal = self.driver.find_element_by_id("weightloss.constellation.education.tools:id/button_equal")
#通過ID找到結果
real_result = self.driver.find_element_by_id("weightloss.constellation.education.tools:id/display")
#點選7
seven.click()
#點選+
plus.click()
#點選3
three.click()
#點選=
equal.click()
結果判斷
在找到元素並對元素進行相應操作後,需要確認結果是否符合預期
結果判斷有兩種方式:
- 斷言
- assertEqual(a, b)---判斷a==b
- assertNotEqual(a, b)---判斷a!=b
- assertTrue(x)---bool(x) is True
- assertFalse(x)---bool(x) is False
- 截圖對比
- get_screenshot_as_file(self, filename)
- save_screenshot(self, filename)
- get_screenshot_as_png(self)
- get_screenshot_as_base64(self)
在 test_plus() 裡新增斷言和截圖:
def test_plus(self):
#預期結果等於10
result = "10"
#通過ID找到7
seven = self.driver.find_element_by_id("weightloss.constellation.education.tools:id/button_7")
#通過ID找到3
three = self.driver.find_element_by_id("weightloss.constellation.education.tools:id/button_3")
#通過ID找到+
plus = self.driver.find_element_by_id("weightloss.constellation.education.tools:id/button_plus")
#通過ID找到=
equal = self.driver.find_element_by_id("weightloss.constellation.education.tools:id/button_equal")
#通過ID找到結果
real_result = self.driver.find_element_by_id("weightloss.constellation.education.tools:id/display")
#點選7
seven.click()
#點選+
plus.click()
#點選3
three.click()
#點選=
equal.click()
#斷言結果是否相等
self.assertEqual(real_result.text, result)
#截圖
self.driver.get_screenshot_as_file(self.SCREEN_SHOT_PATH + "plus_result.png")
報告展示
當執行完所有的 test case 後,如何以直觀的形式展示結果?
Github 上有一個開源專案---HtmlTestRunner,能夠以 HTML 的形式輸出報告。
1、安裝 HtmlTestRunner
pip install html-testRunner
2、匯入 HtmlTestRunner 模組,使用 HTMLTestRunner 替換 unittest.TextTestRunner
#匯入HtmlTestRunner
import HtmlTestRunner
...
#程式入口
if __name__ == '__main__':
#TestSuite,將所有測試用例載入suite
suite = unittest.TestLoader().loadTestsFromTestCase(CalculatorTest)
#TestRunner,執行測試用例
# unittest.TextTestRunner(verbosity=2).run(suite)
#執行case+輸出報告
runner = HtmlTestRunner.HTMLTestRunner(output='cc_report')
runner.run(suite)
示例:
附上完整的程式碼:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Author : Shengjie.Liu
# @Time : 2019-06-03 14:47
# @File : calculator_test.py
# @Desc :
#匯入unittest測試框架
import unittest
#匯入appium客戶端庫
from appium import webdriver
#匯入time模組
from time import sleep
#匯入HtmlTestRunner
import HtmlTestRunner
class CalculatorTest(unittest.TestCase):
# pass
# 截圖路徑
SCREEN_SHOT_PATH = "/Users/liushengjie/PycharmProjects/AppiumTest/share/"
#SetUP,case執行前的環境初始化
def setUp(self):
# pass
#字典變數,初始化配置,提供建立session的所有必要資訊:http://appium.io/docs/en/writing-running-appium/caps/index.html
desired_caps = {}
#被測應用平臺:iOS/Android
desired_caps['platformName'] = 'Android'
#被測應用平臺版本:adb shell getprop ro.build.version.release
desired_caps['platformVersion'] = '8.0.0'
#測試裝置名:adb devices
desired_caps['deviceName'] = 'CB512FCM14'
#被測應用包名
desired_caps['appPackage'] = 'weightloss.constellation.education.tools'
#被測應用啟動時的活動名
desired_caps['appActivity'] = 'com.weightloss.constellation.education.tools.SplashActivityAlias'
#服務端等待客戶端傳送訊息的超時時間
desired_caps['newCommandTimeout'] = 150
#在一個session開始前不重置被測程式的狀態
desired_caps['noReset'] = True
#是否支援uicode的鍵盤(輸入中文需設定)
desired_caps['unicodeKeyboard'] = True
#以desired_caps作為引數初始化WebDriver連線
#Appium伺服器的IP:http://localhost
#埠號:4723
self.driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)
sleep(10)
#TearDown,case執行後的環境恢復
def tearDown(self):
# pass
#退出driver,關閉被測應用所有的關聯視窗
self.driver.quit()
#TestCase,測試用例1
def test_case_1(self):
pass
def test_plus(self):
#預期結果等於10
result = "10"
#通過ID找到7
seven = self.driver.find_element_by_id("weightloss.constellation.education.tools:id/button_7")
#通過ID找到3
three = self.driver.find_element_by_id("weightloss.constellation.education.tools:id/button_3")
#通過ID找到+
plus = self.driver.find_element_by_id("weightloss.constellation.education.tools:id/button_plus")
#通過ID找到=
equal = self.driver.find_element_by_id("weightloss.constellation.education.tools:id/button_equal")
#通過ID找到結果
real_result = self.driver.find_element_by_id("weightloss.constellation.education.tools:id/display")
#點選7
seven.click()
#點選+
plus.click()
#點選3
three.click()
#點選=
equal.click()
#斷言結果是否相等
self.assertEqual(real_result.text, result)
#截圖
self.driver.get_screenshot_as_file(self.SCREEN_SHOT_PATH + "plus_result.png")
#程式入口
if __name__ == '__main__':
#TestSuite,將所有測試用例載入suite
suite = unittest.TestLoader().loadTestsFromTestCase(CalculatorTest)
#TestRunner,執行測試用例
# unittest.TextTestRunner(verbosity=2).run(suite)
#執行case+輸出報告
runner = HtmlTestRunner.HTMLTestRunner(output='cc_report')
runner.run(suite)
此份文件僅做拋磚引玉之用,希望同學們可以根據此文件完成第一個 UI 自動化測試用例。至於之後的編寫,需要大家勤查資料,多看官網