網(wǎng)站首頁 編程語言 正文
PO模式簡介
1.什么是PO模式
PO模型是:Page Object Model的簡寫 頁面對象模型
作用:就是把測試頁面和測試腳本進行分離,即把頁面封裝成類,供測試腳本進行調用;
分層機制,讓不同層去做不同類型的事情,讓代碼結構清晰,增加復用性。
PO設計模式是Selenium自動化測試中最佳的設計模式之一,主要體現(xiàn)在對界面交互細節(jié)的封裝
2. 不使用PO設計會出現(xiàn)以下幾種情況:
復用性不太好,擴展性不好,易讀性差,不好維護,UI界面頻繁的項目維護起來比較麻煩。
3.PO模式的優(yōu)缺點
優(yōu)點:
- 提高代碼的可讀性
- 減少了代碼的重復
- 提高代碼的可維護性,特別是針對UI界面頻繁的項目
缺點:
- 造成項目結構比較復雜,因為是根據(jù)流程進行了模塊化處理
下面重點看下PO模式在selenium自動化測試框架的優(yōu)勢。
PO模式是在UI自動化測試過程當中使用非常頻繁的一種設計模式,使用這種模式后,可以有效的提升代碼的復用能力,并且讓自動化測試代碼維護起來更加方便。
PO模式的全稱叫page object model(POM),有時候叫做 page object pattern。最開始由馬丁福勒提出,這個模式受到selenium自動化測試框架大力推廣,因而成為一種非常主流的自動化測試設計模式。
在PO模式當中,每一個UI頁面使用編程語言當中的類來表示。在這個類當中,通過函數(shù)形式定義頁面的行為和操作。這讓調用方不需要關注具體執(zhí)行的操作到底是點擊還是拖動,而是關注具體的業(yè)務,比如登錄、購物等等,甚至如果程序員直接把代碼給產(chǎn)品經(jīng)理看,他也是能看懂的。
沒有使用PO模式時
在測試用例中直接編寫瀏覽器操作API,對于代碼編寫者并沒有多高的難度,因為他自己已經(jīng)對這些API非常熟悉,但是這些瀏覽器操作并不能體現(xiàn)業(yè)務,至少沒有產(chǎn)品經(jīng)理那么熟悉,因此他很難和產(chǎn)品經(jīng)理進行溝通,也難和開發(fā)溝通,甚至在半個月之后,他已經(jīng)忘記了自己到底寫了什么東西。
def test_login_mail(self): driver = self.driver driver.get("http://www.xxx.xxx.com") driver.find_element_by_id("idInput").clear() driver.find_element_by_id("xxxxxxx").send_keys("xxxxx") driver.find_element_by_id("xxxxxxx").clear() driver.find_element_by_id("xxxxxxx").send_keys("xxxxxx") driver.find_element_by_id("loginBtn").click()
使用PO模式
使用PO模式有利于梳理業(yè)務,也有利于和其他人進行溝通。當你把下面這段代碼拿給產(chǎn)品經(jīng)理看的時候,他也大概能知道你測的是什么業(yè)務,能幫你糾正你的測試流程是否正確,或者提出一些更有建設性的意見,這對于大型項目需要頻繁溝通和梳理業(yè)務時非常有用。
def test_login_mail(self): LoginPage(driver).login()
而瀏覽器本身的操作,就會被分離到一個更底層的模塊,這些代碼你可以不對調用方暴露,產(chǎn)品經(jīng)理并不關心你這個頁面中什么元素定位,他也不懂。
class LoginPage: username_loc=(By.ID,"idInput") password_loc =(By.ID,"pwdInput") submit_loc =(By.ID,"loginBtn") span_loc=(By.CSS_SELECTOR,"div.error-tt>p") dynpw_loc =(By.ID,"lbDynPw") userid_loc =(By.ID,"spnUid") def __init__(self, driver): self.driver = driver def login(self): self.driver.find_element(*self.username_loc).clear() self.driver.find_element(*self.username_loc).send_keys("xxxxx") self.driver.find_element(*self.password_loc).clear() self.driver.find_element(*self.password_loc).send_keys("xxxxxx") self.driver.find_element(*self.submit_loc).click()
這種方式把元素定位方式也分離了。但是這種元素定位的表達式可讀性也不是很強,可以換用 property 方式來表示元素,所有的元素統(tǒng)一放在一起,修改起來也比較方便。
class LoginPage: def __init__(self, driver) self.driver = driver @property def username_element(self): return self.driver.find_element('id', 'idInput') def password_element(self): return self.driver.find_element('id', 'pwdInput') def submit_element(self): return self.driver.find_element('id', 'loginBtn') def login(self, name, password): self.username_element.send_keys(name) self.password_element.send_keys(password) self.submit_element.click()
第三種方式可以充分利用Python的描述符特性,你會發(fā)現(xiàn)很多序列化庫或者ORM框架都有類似的用法。
class LoginPage: def __init__(self, driver) self.driver = driver username = Element(css='#idInput', desc='用戶名輸入框') password = Element(css='#pwdInput', desc='密碼輸入框') confirm = Element(css='#loginBtn', desc='登錄確認按鈕') def login(self, name, password): self.username.send_keys(name) self.password.send_keys(password) self.confirm.click()
而 Element 類可以通過 Python 描述符實現(xiàn),這里為了方便,只定義了xpath的元素定位方法:
class Element: def __init__(self,xpath=None,desc=''): self.xpath = xpath self.desc = desc def __get__(self, instance, owner): driver = instance.browser el = driver.find_element('xpath', self.xpath) return el
PO模式和DDD
PO模式是DDD(領域驅動設計)的一個簡單實現(xiàn),但是還不夠徹底。如果要在自動化測試中貫徹DDD,我覺得還有一些可以優(yōu)化的空間。
首先某一個業(yè)務不一定只是單個頁面的操作,比如登錄不一定只涉及到LoginPage這個頁面,因此直接在LoginPage中編寫login函數(shù)就不是很合理。對于調用方來說,應該明確說明的是誰在登錄,而不是指某個頁面。像這樣:
user.login() # or login(user)
我們編寫的代碼就像是自然語言,任何懂英語的人都知道代碼在做什么,在DDD中,叫做領域特定語言(DSL), 要實現(xiàn)這種邏輯,在Page類和調用中間應該還會有一個層級來封裝user。
其次,Page頁面會依賴更底層的資源,比如組件,元素類型。因此在 Page 類的下方應該會使用 InputElement, ButtonElement 、SelectElement 這樣的元素類和 HeaderComponent、FooterComponent 這樣的組件類。
class LoginPage: username_filed = InputElement('xxx') password_filed = PasswordElement('xxx')
領域驅動設計對于大型項目梳理業(yè)務、同步業(yè)務、溝通業(yè)務是非常有幫助的,是一種以業(yè)務為中心的設計范式。PO模式對于DDD的小范圍應用,以及具體了足夠多的好處:
- 便于維護。每一個頁面的操作都被單獨的存放在一個類文件中,當前端頁面被修改之后,只需要找到對應類文件進行修改,其他的代碼并不需要進行修改,這符合單一職責原則。
- 便于重復使用。在進行自動化測試的時候,一個測試由多個測試步驟組成,這些測試步驟可能涉及到多個頁面的操作。而用例與用例之間的操作可能重合。PO模式可以重復利用這些測試步驟,簡化代碼的編寫。
- 提高了可讀性。頁面的操作都被以函數(shù)的形式封裝起來了。函數(shù)名就具備注釋的作用,其他人閱讀代碼時可以通過函數(shù)了解業(yè)務。
原文鏈接:https://www.cnblogs.com/heniu/archive/2022/03/19/16028064.html
相關推薦
- 2022-12-03 高并發(fā)技巧之Redis和本地緩存使用技巧分享_Redis
- 2022-08-22 Python利用字典和列表實現(xiàn)學生信息管理系統(tǒng)_python
- 2023-02-07 go?reflect要不要傳指針原理詳解_Golang
- 2022-08-31 Flask接收上傳圖片方法實現(xiàn)_python
- 2023-04-06 rust解決嵌套——Option類型的map和and_then方法的使用_Rust語言
- 2022-07-30 jQuery?UI工具提示框部件Tooltip?Widget_jquery
- 2023-05-08 C語言超詳細講解雙向帶頭循環(huán)鏈表_C 語言
- 2022-04-20 用Python實現(xiàn)插值算法_python
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細win安裝深度學習環(huán)境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結構-簡單動態(tài)字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支