網(wǎng)站首頁(yè) 編程語言 正文
PO模式簡(jiǎn)介
1.什么是PO模式
PO模型是:Page Object Model的簡(jiǎn)寫 頁(yè)面對(duì)象模型
作用:就是把測(cè)試頁(yè)面和測(cè)試腳本進(jìn)行分離,即把頁(yè)面封裝成類,供測(cè)試腳本進(jìn)行調(diào)用;
分層機(jī)制,讓不同層去做不同類型的事情,讓代碼結(jié)構(gòu)清晰,增加復(fù)用性。
PO設(shè)計(jì)模式是Selenium自動(dòng)化測(cè)試中最佳的設(shè)計(jì)模式之一,主要體現(xiàn)在對(duì)界面交互細(xì)節(jié)的封裝
2. 不使用PO設(shè)計(jì)會(huì)出現(xiàn)以下幾種情況:
復(fù)用性不太好,擴(kuò)展性不好,易讀性差,不好維護(hù),UI界面頻繁的項(xiàng)目維護(hù)起來比較麻煩。
3.PO模式的優(yōu)缺點(diǎn)
優(yōu)點(diǎn):
- 提高代碼的可讀性
- 減少了代碼的重復(fù)
- 提高代碼的可維護(hù)性,特別是針對(duì)UI界面頻繁的項(xiàng)目
缺點(diǎn):
- 造成項(xiàng)目結(jié)構(gòu)比較復(fù)雜,因?yàn)槭歉鶕?jù)流程進(jìn)行了模塊化處理
下面重點(diǎn)看下PO模式在selenium自動(dòng)化測(cè)試框架的優(yōu)勢(shì)。
PO模式是在UI自動(dòng)化測(cè)試過程當(dāng)中使用非常頻繁的一種設(shè)計(jì)模式,使用這種模式后,可以有效的提升代碼的復(fù)用能力,并且讓自動(dòng)化測(cè)試代碼維護(hù)起來更加方便。
PO模式的全稱叫page object model(POM),有時(shí)候叫做 page object pattern。最開始由馬丁福勒提出,這個(gè)模式受到selenium自動(dòng)化測(cè)試框架大力推廣,因而成為一種非常主流的自動(dòng)化測(cè)試設(shè)計(jì)模式。
在PO模式當(dāng)中,每一個(gè)UI頁(yè)面使用編程語言當(dāng)中的類來表示。在這個(gè)類當(dāng)中,通過函數(shù)形式定義頁(yè)面的行為和操作。這讓調(diào)用方不需要關(guān)注具體執(zhí)行的操作到底是點(diǎn)擊還是拖動(dòng),而是關(guān)注具體的業(yè)務(wù),比如登錄、購(gòu)物等等,甚至如果程序員直接把代碼給產(chǎn)品經(jīng)理看,他也是能看懂的。
沒有使用PO模式時(shí)
在測(cè)試用例中直接編寫瀏覽器操作API,對(duì)于代碼編寫者并沒有多高的難度,因?yàn)樗约阂呀?jīng)對(duì)這些API非常熟悉,但是這些瀏覽器操作并不能體現(xiàn)業(yè)務(wù),至少?zèng)]有產(chǎn)品經(jīng)理那么熟悉,因此他很難和產(chǎn)品經(jīng)理進(jìn)行溝通,也難和開發(fā)溝通,甚至在半個(gè)月之后,他已經(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è)務(wù),也有利于和其他人進(jìn)行溝通。當(dāng)你把下面這段代碼拿給產(chǎn)品經(jīng)理看的時(shí)候,他也大概能知道你測(cè)的是什么業(yè)務(wù),能幫你糾正你的測(cè)試流程是否正確,或者提出一些更有建設(shè)性的意見,這對(duì)于大型項(xiàng)目需要頻繁溝通和梳理業(yè)務(wù)時(shí)非常有用。
def test_login_mail(self): LoginPage(driver).login()
而瀏覽器本身的操作,就會(huì)被分離到一個(gè)更底層的模塊,這些代碼你可以不對(duì)調(diào)用方暴露,產(chǎn)品經(jīng)理并不關(guān)心你這個(gè)頁(yè)面中什么元素定位,他也不懂。
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()
這種方式把元素定位方式也分離了。但是這種元素定位的表達(dá)式可讀性也不是很強(qiáng),可以換用 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的描述符特性,你會(huì)發(fā)現(xiàn)很多序列化庫(kù)或者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='登錄確認(rèn)按鈕') def login(self, name, password): self.username.send_keys(name) self.password.send_keys(password) self.confirm.click()
而 Element 類可以通過 Python 描述符實(shí)現(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(領(lǐng)域驅(qū)動(dòng)設(shè)計(jì))的一個(gè)簡(jiǎn)單實(shí)現(xiàn),但是還不夠徹底。如果要在自動(dòng)化測(cè)試中貫徹DDD,我覺得還有一些可以優(yōu)化的空間。
首先某一個(gè)業(yè)務(wù)不一定只是單個(gè)頁(yè)面的操作,比如登錄不一定只涉及到LoginPage這個(gè)頁(yè)面,因此直接在LoginPage中編寫login函數(shù)就不是很合理。對(duì)于調(diào)用方來說,應(yīng)該明確說明的是誰在登錄,而不是指某個(gè)頁(yè)面。像這樣:
user.login() # or login(user)
我們編寫的代碼就像是自然語言,任何懂英語的人都知道代碼在做什么,在DDD中,叫做領(lǐng)域特定語言(DSL), 要實(shí)現(xiàn)這種邏輯,在Page類和調(diào)用中間應(yīng)該還會(huì)有一個(gè)層級(jí)來封裝user。
其次,Page頁(yè)面會(huì)依賴更底層的資源,比如組件,元素類型。因此在 Page 類的下方應(yīng)該會(huì)使用 InputElement, ButtonElement 、SelectElement 這樣的元素類和 HeaderComponent、FooterComponent 這樣的組件類。
class LoginPage: username_filed = InputElement('xxx') password_filed = PasswordElement('xxx')
領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)對(duì)于大型項(xiàng)目梳理業(yè)務(wù)、同步業(yè)務(wù)、溝通業(yè)務(wù)是非常有幫助的,是一種以業(yè)務(wù)為中心的設(shè)計(jì)范式。PO模式對(duì)于DDD的小范圍應(yīng)用,以及具體了足夠多的好處:
- 便于維護(hù)。每一個(gè)頁(yè)面的操作都被單獨(dú)的存放在一個(gè)類文件中,當(dāng)前端頁(yè)面被修改之后,只需要找到對(duì)應(yīng)類文件進(jìn)行修改,其他的代碼并不需要進(jìn)行修改,這符合單一職責(zé)原則。
- 便于重復(fù)使用。在進(jìn)行自動(dòng)化測(cè)試的時(shí)候,一個(gè)測(cè)試由多個(gè)測(cè)試步驟組成,這些測(cè)試步驟可能涉及到多個(gè)頁(yè)面的操作。而用例與用例之間的操作可能重合。PO模式可以重復(fù)利用這些測(cè)試步驟,簡(jiǎn)化代碼的編寫。
- 提高了可讀性。頁(yè)面的操作都被以函數(shù)的形式封裝起來了。函數(shù)名就具備注釋的作用,其他人閱讀代碼時(shí)可以通過函數(shù)了解業(yè)務(wù)。
原文鏈接:https://www.cnblogs.com/heniu/archive/2022/03/19/16028064.html
相關(guān)推薦
- 2022-04-26 EF?Core通過顯式編譯提高查詢性能_實(shí)用技巧
- 2022-11-19 Gogs遷移
- 2023-07-26 TypeScript中的模塊與命名空間
- 2022-10-06 Python?Numpy中數(shù)組的集合操作詳解_python
- 2022-12-07 Rust?for循環(huán)語法糖背后的API場(chǎng)景分析_Rust語言
- 2022-03-27 C++命名空間和缺省參數(shù)介紹_C 語言
- 2022-05-05 Python學(xué)習(xí)之集合的常用方法總結(jié)_python
- 2022-06-02 C語言循環(huán)隊(duì)列與用隊(duì)列實(shí)現(xiàn)棧問題解析_C 語言
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲(chǔ)小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡(jiǎn)單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對(duì)象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支