1. 程式人生 > >Appium入門指南 - 環境搭建和Case編寫

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 三大系統。因為安裝過程實在是太簡單了,所以不做詳細說明。

2、通過命令列的方式進行安裝,這個比較複雜,需要依次下載安裝多種配置/依賴來滿足 Appium 的執行條件。著重介紹此種安裝方式。

命令列安裝

以下命令都是在終端(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 自動化測試用例。至於之後的編寫,需要大家勤查資料,多看官網