WebDriver 封裝
歡迎閱讀WebDriver封裝講義。本篇講義將會重點介紹Selenium WebDriver API的封裝的概念和方法,以及使用封裝進(jìn)行自動化測試的設(shè)計。
WebDriver API 封裝
封裝的概念
從之前的講義和學(xué)習(xí)中,我們知道,WebDriver API的調(diào)用以及自動化測試,我們也初步接觸了線性測試、以及模塊化自動化測試和數(shù)據(jù)驅(qū)動測試,那么回顧之前的內(nèi)容,我們不只是可以利用WebDriver提供的一系列的定位符以便使用元素定位方法,我們這里開始嘗試封裝后調(diào)用。首先,我們從封裝的概念開始。
封裝是一個面向?qū)ο缶幊痰母拍睿敲嫦驅(qū)ο缶幊痰暮诵膶傩?,通過將代碼內(nèi)部實現(xiàn)進(jìn)行密封和包裝,從而簡化編程。
所謂“對象”,形象地說,我們可以把它理解為一塊積木。設(shè)計積木的人需要設(shè)計積木的外觀與形狀,還有內(nèi)部的材質(zhì)。堆積木的人對于內(nèi)部的材質(zhì)并不關(guān)心,他們只需要根據(jù)不同的外觀與形狀來決定堆放的位置。因此,對于開發(fā)者而言,要設(shè)計面向?qū)ο蟮某绦?,同時會是兩個迥然不同的身份:設(shè)計者與使用者。
先談?wù)勈褂谜?。使用者的身份,就是利用已?jīng)提供給你的所有對象,根據(jù)需求,設(shè)計出自己需要實現(xiàn)的程 序。就如堆積木的過程。這恰恰是面向?qū)ο缶幊痰膬?yōu)勢所在,那就是“對象的重用”。已經(jīng)設(shè)計好的對象,可以被不同的使用者調(diào)用,這些功能既然已經(jīng)實現(xiàn),對于使用者而言,當(dāng)然就免去了自己去設(shè)計的過程。正如堆積木那樣,既然有了現(xiàn)成設(shè)計好的積木,使用者所要做的工作就是把這些積木最后組合起來,堆成不同的形狀。WebDriver所提供的類庫,就是這樣的積木。那么我們以下的操作將會基于上述的定位符進(jìn)行定位操作。
前面說到對象好比是一個積木,設(shè)計者需要定義好這個積木的外觀和形狀,也要考慮積木內(nèi)部的制作,例如選用的材質(zhì),以及是空心還是實心。如果將這個積木剖開來看,實際上該對象應(yīng)分為內(nèi)、外兩層。由于使用者只關(guān)心外部的實現(xiàn),因此設(shè)計者就需要考慮,哪些實現(xiàn)應(yīng)暴露在外,哪些實現(xiàn)應(yīng)隱藏于內(nèi)。這就體現(xiàn)了對象的封裝的思想。
簡而言之,封裝就是把原始和原生的方法進(jìn)行再包裝。將原始的代碼用心的代碼包裝起來,通過對新代碼的調(diào)用,來使用原始的代碼的過程。
封裝的好處
對Selenium進(jìn)行封裝的好處主要有如下三個方面:
- 使用成本低
- 不需要要求所有的測試工程師會熟練使用Selenium,而只需要會使用封裝以后的代碼
- 不需要對所有的測試工程師進(jìn)行完整培訓(xùn)。也避免工作交接的成本。
- 測試人員使用統(tǒng)一的代碼庫
- 維護(hù)成本低
- 通過封裝,在代碼發(fā)生大范圍變化和遷移的時候,不需要維護(hù)所有代碼,只需要變更封裝的部分即可
- 維護(hù)代碼不需要有大量的工程師,只需要有核心的工程師進(jìn)行封裝的維護(hù)即可
- 代碼安全性
- 對作為第三方的Selenium進(jìn)行封裝,是代碼安全的基礎(chǔ)。
- 對于任何的代碼的安全隱患,必須由封裝來解決,使得風(fēng)險可控。
- 使用者并不知道封裝內(nèi)部的代碼結(jié)構(gòu)。
封裝的目的
封裝,最終為了實現(xiàn)自動化測試框架。在自動化測試領(lǐng)域,有一個經(jīng)典的問題:“既然可以編寫或者通過record & playback可以做一個腳本,那么為什么還需要自動化測試框架呢?”簡而言之,就是為什么需要如此這般麻煩的設(shè)計和編寫自動化測試框架,不是原本已經(jīng)可以做自動化測試了么?
這個回答可以很“官方”,從維護(hù)性、重用性、安全性和成本等角度可以回答。
在這點,就好比是建造房子。在沒有設(shè)計框架的基礎(chǔ)上,我們或許可以建造一個樓房,最多也就三兩層吧;但是對于一份經(jīng)過完整設(shè)計的圖紙,人們可以建造出高樓大廈。
封裝,就是把基礎(chǔ)的石頭等建材,通過我們的個性化的方法,將地基可用而安全的搭建好。是自動化測試框架的基石。
使用封裝進(jìn)行自動化測試
封裝示例
測試腳本:以下的腳本
def getElement(self, selector):
"""
to locate element by selector
:arg
selector should be passed by an example with "i,xxx"
"x,//*[@id='langs']/button"
:returns
DOM element
"""
if ',' not in selector:
return self.driver.find_element_by_id(selector)
selector_by = selector.split(',')[0]
selector_value = selector.split(',')[1]
if selector_by == "i" or selector_by == 'id':
element = self.driver.find_element_by_id(selector_value)
elif selector_by == "n" or selector_by == 'name':
element = self.driver.find_element_by_name(selector_value)
elif selector_by == "c" or selector_by == 'class_name':
element = self.driver.find_element_by_class_name(selector_value)
elif selector_by == "l" or selector_by == 'link_text':
element = self.driver.find_element_by_link_text(selector_value)
elif selector_by == "p" or selector_by == 'partial_link_text':
element = self.driver.find_element_by_partial_link_text(selector_value)
elif selector_by == "t" or selector_by == 'tag_name':
element = self.driver.find_element_by_tag_name(selector_value)
elif selector_by == "x" or selector_by == 'xpath':
element = self.driver.find_element_by_xpath(selector_value)
elif selector_by == "s" or selector_by == 'selector_selector':
element = self.driver.find_element_by_css_selector(selector_value)
else:
raise NameError("Please enter a valid type of targeting elements.")
return element
def type(self, selector, text):
"""
Operation input box.
Usage:
driver.type("i,el","selenium")
"""
el = self.getElement(selector)
el.clear()
el.send_keys(text)
以上的代碼是封裝了find_element_by_的幾種方法,在具體使用封裝過的代碼的時候,只需要簡單的調(diào)用即可。
調(diào)用示例
def login(self, userName, password):
self.openPage(self.loginPageUrl)
# self.driver.clearCookies()
self.driver.implicitlyWait(5)
self.driver.type("account", userName)
self.driver.type("password", password)
self.driver.click("submit")
自動化的測試代碼示例
def test_ranzhi_login(self):
"""
測試用例:測試然之登錄
:return:
"""
# 新建然之的頁面對象
loginPage = RanzhiSubLoginPage(self.autoDriver, self.baseUrl)
# 利用然之的頁面對象進(jìn)行登錄
loginPage.login("admin", "admin")
sleep(2)
# 斷言 是否登錄成功
self.assertEqual(loginPage.getMainPage(), self.autoDriver.getUrl(), u"登錄失敗")