本文節(jié)選自霍格沃茲《測試開發(fā)實(shí)戰(zhàn)進(jìn)階》課程教學(xué)內(nèi)容壶硅,進(jìn)階學(xué)習(xí)文末加群。
在 UI 自動化測試過程中芙粱,面對復(fù)雜的業(yè)務(wù)場景划咐,經(jīng)常會遇到這樣的挑戰(zhàn):
- 簡單的錄制/回放速度快拴念,但無法適應(yīng)復(fù)雜場景;
- 編寫自動化測試腳本比較靈活褐缠,但工作量大且可維護(hù)性差政鼠;
- 以往的封裝技術(shù)(PageObject)可以適應(yīng)各種 UI 場景,但結(jié)構(gòu)松散队魏,無法在多項(xiàng)目中遷移公般;
因此万搔,測試團(tuán)隊(duì)通常還需要一種定制測試框架,用以彌補(bǔ)現(xiàn)有框架的缺點(diǎn)官帘。
測試框架封裝思想
由于 UI 自動化測試框架圍繞 UI 界面使用瞬雹,因此,依舊選用 PageObject 設(shè)計(jì)模式對 UI 及測試進(jìn)行封裝刽虹,同時(shí)配合 Pytest 單元測試將腳本能夠有效的組織酗捌、連貫應(yīng)用起來,從而提高框架的可維護(hù)性和可讀性涌哲。
由于測試框架基于 PageObject 設(shè)計(jì)模式胖缤,主要方向?yàn)?PO 改進(jìn),數(shù)據(jù)驅(qū)動阀圾,異常處理等哪廓,比如:
- 測試數(shù)據(jù)的數(shù)據(jù)驅(qū)動:將數(shù)據(jù)存儲到外部 yaml 文件中,利用 yaml 工具進(jìn)行數(shù)據(jù)讀壬缘丁撩独;
- 數(shù)據(jù)步驟的數(shù)據(jù)驅(qū)動:將操作步驟放到外部 yaml 文件中敞曹,利用 yaml 工具對操作步驟進(jìn)行讀取账月,用專門函數(shù)解析并實(shí)現(xiàn)操作步驟;
- 自動化異常處理機(jī)制:對元素查找模塊進(jìn)行封裝和改進(jìn)澳迫,包括如何處理彈窗局齿;
Page_Object 改造
作為通用的 UI 測試框架, PageObjet 不僅適用于 Web 自動化測試橄登,也可適用 Appium 移動自動化測試抓歼,其優(yōu)點(diǎn)如下:
- 減少代碼重復(fù)
- 提高測試用例可讀性
- 提高測試用例可維護(hù)性
[圖片上傳失敗...(image-baa165-1653040789184)]
PO 改造實(shí)例(基于雪球 App)
本案例將對雪球 App 進(jìn)行 Page Objetct 封裝與改進(jìn)。
當(dāng)啟動雪球 App 時(shí)拢锹,會進(jìn)入首頁谣妻。點(diǎn)擊搜索框進(jìn)入搜索頁,搜索某支股票然后判斷股價(jià)是否大于 200:
[圖片上傳失敗...(image-ebc1d3-1653040789184)]
PageObjetct 的模塊關(guān)系如下卒稳,所有的模塊要繼承 BasePage 蹋半, App 實(shí)現(xiàn)啟動,重啟充坑,停止等操作减江, Main 實(shí)現(xiàn)進(jìn)入搜索頁,進(jìn)入股票頁等操作:
[圖片上傳失敗...(image-f9e219-1653040789184)]
base_page 模塊是所有 page 類的父類捻爷,其中定義了公共方法辈灼,比如封裝下面的 find 方法后,可以讓子類調(diào)用 find :
from appium.webdriver.webdriver import WebDriver
class BasePage:
_driver: WebDriver
def __init__(self, driver: WebDriver = None):
self._driver = driver
def find(self, locator, value: str = None):
#如果傳進(jìn)來的是tuple也榄,只需使用一個(gè)參數(shù):locator
if isinstance(locator, tuple):
return self._driver.find_element(*locator)
else:
return self._driver.find_element(locator, value)
App 模塊封裝 app 的啟動巡莹,重啟,停止等方法,當(dāng) app 啟動時(shí)會進(jìn)入 main 頁面降宅,因此在下面的 main 方法要 return Main 俐芯,Main 類的定義在后面會講解:
from appium import webdriver
from test_appium.page.base_page import BasePage
from test_appium.page.main import Main
class App(BasePage):
#指定app的包名和activity名
_package = "com.xueqiu.android"
_activity = ".view.WelcomeActivityAlias"
def start(self):
#如果driver為空則初始化
if self._driver is None:
caps = {}
caps["platformName"] = "android"
caps["deviceName"] = "hogwarts"
caps["appPackage"] = self._package
caps["appActivity"] = self._activity
caps["noReset"] = True
#初始化driver
self._driver = webdriver.Remote("http://localhost:4723/wd/hub", caps)
self._driver.implicitly_wait(30)
#如果driver不為空,則直接啟動activity
else:
print(self._driver)
self._driver.start_activity(self._package, self._activity)
return self
def restart(self):
pass
def stop(self):
pass
def main(self) -> Main:
#當(dāng)app啟動時(shí)钉鸯,跳轉(zhuǎn)到(實(shí)例化)Main
return Main(self._driver)
Main 模塊是首頁的 PageObject 吧史,其中的方法封裝了首頁的重要功能,比如下面代碼中的 goto_search_page 封裝了點(diǎn)擊搜索并跳轉(zhuǎn)到 Search 頁:
from appium.webdriver.common.mobileby import MobileBy
from selenium.webdriver.common.by import By
from test_appium.page.base_page import BasePage
from test_appium.page.profile import Profile
from test_appium.page.search import Search
class Main(BasePage):
#點(diǎn)擊搜索按鈕后唠雕,進(jìn)入搜索頁
def goto_search_page(self):
self.find(MobileBy.ID, "tv_search").click()
#進(jìn)入搜索頁
return Search(self._driver)
def goto_stocks(self):
pass
def goto_trade(self):
pass
def goto_messages(self):
pass
Search 模塊可以搜索一支股票贸营,還可以獲取股票的價(jià)格,比如下圖:
[圖片上傳失敗...(image-fdeb78-1653040789184)]
封裝代碼如下:
from appium.webdriver.common.mobileby import MobileBy
from selenium.webdriver.remote.webdriver import WebDriver
class Search:
_driver: WebDriver
def __init__(self, driver):
self._driver = driver
#輸入要搜索的內(nèi)容
def search(self, key: str):
self._driver.find_element(MobileBy.ID, "search_input_text").send_keys(key)
self._driver.find_element(MobileBy.ID, "name").click()
return self
#獲取股票價(jià)格岩睁,用于判斷
def get_price(self, key: str) -> float:
return float(self._driver.find_element(MobileBy.ID, "current_price").text)
最后對上述代碼建立測試钞脂,新建測試模塊 test_search :
import pytest
from test_appium.page.app import App
class TestSearch:
def setup(self):
self.main = App().start().main()
def test_search(self):
assert self.main.goto_search_page().search("alibaba").get_price("BABA") > 200
以上,供大家參考捕儒,歡迎一起留言探討冰啃。
獲取更多相關(guān)資料:請?zhí)砑觱x,ceshiren001
https://qrcode.ceba.ceshiren.com/link?name=article&project_id=qrcode&from=jianshu×tamp=1653037966&author=MM