Python Selenium設(shè)計(jì)模式及代碼實(shí)現(xiàn)
下方查看歷史精選文章
大數(shù)據(jù)測(cè)試過(guò)程、策略及挑戰(zhàn)
前言
本文就python selenium自動(dòng)化測(cè)試實(shí)踐中所需要的POM設(shè)計(jì)模式進(jìn)行分享,以便大家在實(shí)踐中對(duì)POM的特點(diǎn)、應(yīng)用場(chǎng)景和核心思想有一定的理解和掌握。
為什么要用POM
基于python selenium2開始UI級(jí)自動(dòng)化測(cè)試并不是多么艱巨的任務(wù)。**只需要定位到元素,執(zhí)行對(duì)應(yīng)的操作即可。**下面我們看一下這個(gè)簡(jiǎn)單的腳本實(shí)現(xiàn)百度搜索。
from selenium import webdriverimport timedriver = webdriver.Firefox()driver.implicitly_wait(30)# 啟動(dòng)瀏覽器,訪問(wèn)百度driver.get("http://www.baidu.com")# 定位 百度搜索框,并輸入seleniumdriver.find_element_by_id("kw").send_keys("selenium")# 定位 百度一下 按鈕并單擊進(jìn)行搜索driver.find_element_by_id("su").click()time.sleep(5)driver.quit()
從上述代碼來(lái)看,我們所能做的就是定位到元素,然后進(jìn)行鍵盤輸入或鼠標(biāo)動(dòng)作。就這個(gè)小程序而已,維護(hù)起來(lái)看起來(lái)是很容易的。但隨著時(shí)間的遷移,測(cè)試套件將持續(xù)的增長(zhǎng)。腳本也將變得越來(lái)越臃腫龐大。如果變成我們需要維護(hù)10個(gè)頁(yè)面,100個(gè)頁(yè)面,甚至1000個(gè)呢?那頁(yè)面元素的任何改變都會(huì)讓我們的腳本維護(hù)變得繁瑣復(fù)雜,而且變得耗時(shí)易出錯(cuò)。
那怎么解決呢? 在自動(dòng)化測(cè)試中,引入了Page Object Model(POM):頁(yè)面對(duì)象模式來(lái)解決,POM能讓我們的測(cè)試代碼變得可讀性更好,高可維護(hù)性,高復(fù)用性。
下圖為非POM和POM對(duì)比圖:

POM是什么
頁(yè)面對(duì)象模型(POM)是一種設(shè)計(jì)模式,用來(lái)管理維護(hù)一組web元素集的對(duì)象庫(kù)
在POM下,應(yīng)用程序的每一個(gè)頁(yè)面都有一個(gè)對(duì)應(yīng)的page class
每一個(gè)page class維護(hù)著該web頁(yè)的元素集和操作這些元素的方法
page class中的方法命名最好根據(jù)其對(duì)應(yīng)的業(yè)務(wù)場(chǎng)景進(jìn)行,例如通常登錄后我們需要等待幾秒中,我們可以這樣命名該方法: waitingForLoginSuccess().
下面我們看看POM的代碼目錄組織示例:

POM的優(yōu)勢(shì)
POM提供了一種在UI層操作、業(yè)務(wù)流程與驗(yàn)證分離的模式,這使得測(cè)試代碼變得更加清晰和高可讀性
對(duì)象庫(kù)與用例分離,使得我們更好的復(fù)用對(duì)象,甚至能與不同的工具進(jìn)行深度結(jié)合應(yīng)用
可復(fù)用的頁(yè)面方法代碼會(huì)變得更加優(yōu)化
更加有效的命名方式使得我們更加清晰的知道方法所操作的UI元素。例如我們要回到首頁(yè),方法名命名為: gotoHomePage(),通過(guò)方法名即可清晰的知道具體的功能實(shí)現(xiàn)。
POM實(shí)現(xiàn)示例
下面我們看下使用POM百度搜索 POM代碼示例: 看先下代碼組織結(jié)構(gòu)如下:

# basePage.py代碼如下# _*_ coding:utf-8 _*___author__ = '苦葉子'import sysreload(sys)sys.setdefaultencoding("utf-8")# pages基類class Page(object):"""Page基類,所有page都應(yīng)該繼承該類"""def __init__(self, driver, base_url=u"http://www.baidu.com"):self.driver = driverself.base_url = base_urlself.timeout = 30def find_element(self, *loc):return self.driver.find_element(*loc)def input_text(self, loc, text):self.find_element(*loc).send_keys(text)def click(self, loc):self.find_element(*loc).click()def get_title(self):return self.driver.title# searchPage.py 代碼如下# _*_ coding:utf-8 _*___author__ = '苦葉子'import sysfrom selenium.webdriver.common.by import Byfrom pages.basePage import Pagereload(sys)sys.setdefaultencoding("utf-8")# 百度搜索pageclass SearchPage(Page):# 元素集# 搜索輸入框search_input = (By.ID, u'kw')# 百度一下 按鈕search_button = (By.ID, u'su')def __init__(self, driver, base_url=u"http://www.baidu.com"):Page.__init__(self, driver, base_url)def gotoBaiduHomePage(self):print u"打開首頁(yè): ", self.base_urlself.driver.get(self.base_url)def input_search_text(self, text=u"開源優(yōu)測(cè)"):print u"輸入搜索關(guān)鍵字:開源優(yōu)測(cè) "self.input_text(self.search_input, text)def click_search_btn(self):print u"點(diǎn)擊 百度一下 按鈕"self.click(self.search_button)# testSearchPage.py代碼如下# _*_ coding:utf-8 _*___author__ = '苦葉子'import unittestimport sysfrom selenium import webdriverfrom pages.searchPage import SearchPagereload(sys)sys.setdefaultencoding("utf-8")# 百度搜索測(cè)試class TestSearchPage(unittest.TestCase):def setUp(self):self.driver = webdriver.Ie()def testSearch(self):driver = self.driver# 百度網(wǎng)址url = u"http://www.baidu.com"# 搜索文本text = u"開源優(yōu)測(cè)"# 期望驗(yàn)證的標(biāo)題assert_title = u"開源優(yōu)測(cè)_百度搜索"print assert_titlesearch_Page = SearchPage(driver, url)# 啟動(dòng)瀏覽器,訪問(wèn)百度首頁(yè)search_Page.gotoBaiduHomePage()# 輸入 搜索詞search_Page.input_search_text(text)# 單擊 百度一下 按鈕進(jìn)行搜索search_Page.click_search_btn()# 驗(yàn)證標(biāo)題self.assertEqual(search_Page.get_title(), assert_title)def tearDown(self):self.driver.quit()# 主入口程序代碼如下# _*_ coding:utf-8 _*___author__ = '苦葉子'import unittestimport sysfrom common import HTMLTestRunnerfrom testcase.testSearchPageimport TestSearchPagereload(sys)sys.setdefaultencoding("utf-8")if __name__ == '__main__':testunit = unittest.TestSuite()testunit.addTest(TestSearchPage('testSearch'))# 定義報(bào)告輸出路徑htmlPath = u"page_demo_Report.html"fp = file(htmlPath, "wb")runner = HTMLTestRunner.HTMLTestRunner(stream=fp,title=u"百度測(cè)試",description=u"測(cè)試用例結(jié)果")runner.run(testunit)fp.close()
按照如圖所示組織代碼結(jié)構(gòu),輸入如上代碼,執(zhí)行以下命令運(yùn)行,會(huì)在當(dāng)前目錄生成測(cè)試報(bào)告:
python main.py總結(jié)
最后做個(gè)總結(jié),所有代碼請(qǐng)手動(dòng)輸入,不要直接拷貝。再次對(duì)POM進(jìn)行小結(jié)
POM是selenium webdriver自動(dòng)化測(cè)試實(shí)踐對(duì)象庫(kù)設(shè)計(jì)模式
POM使得測(cè)試腳本更易于維護(hù)
POM通過(guò)對(duì)象庫(kù)方式進(jìn)一步優(yōu)化了元素、用例、數(shù)據(jù)的維護(hù)組織


