前言
本文就python selenium自動(dòng)化測(cè)試實(shí)踐中所需要的POM設(shè)計(jì)模式進(jìn)行分享,以便大家在實(shí)踐中對(duì)POM的特點(diǎn)、應(yīng)用場(chǎng)景和核心思想有一定的理解和掌握坞笙。
為什么要用POM
基于python selenium2開(kāi)始UI級(jí)自動(dòng)化測(cè)試并不是多么艱巨的任務(wù)梅猿。只需要定位到元素,執(zhí)行對(duì)應(yīng)的操作即可诵次。下面我們看一下這個(gè)簡(jiǎn)單的腳本實(shí)現(xiàn)百度搜索账蓉。
from selenium import webdriver
import time
driver = webdriver.Firefox()
driver.implicitly_wait(30)
# 啟動(dòng)瀏覽器,訪問(wèn)百度
driver.get("http://www.baidu.com")
# 定位 百度搜索框逾一,并輸入selenium
driver.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)行鍵盤(pá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 sys
reload(sys)
sys.setdefaultencoding("utf-8")
# pages基類(lèi)
class Page(object):
"""
Page基類(lèi)桨螺,所有page都應(yīng)該繼承該類(lèi)
"""
def __init__(self, driver, base_url=u"http://www.baidu.com"):
self.driver = driver
self.base_url = base_url
self.timeout = 30
def 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 sys
from selenium.webdriver.common.by import By
from pages.basePage import Page
reload(sys)
sys.setdefaultencoding("utf-8")
# 百度搜索page
class 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"打開(kāi)首頁(yè): ", self.base_url
self.driver.get(self.base_url)
def input_search_text(self, text=u"開(kāi)源優(yōu)測(cè)"):
print u"輸入搜索關(guān)鍵字: 開(kāi)源優(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 unittest
import sys
from selenium import webdriver
from pages.searchPage import SearchPage
reload(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"開(kāi)源優(yōu)測(cè)"
# 期望驗(yàn)證的標(biāo)題
assert_title = u"開(kāi)源優(yōu)測(cè)_百度搜索"
print assert_title
search_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 unittest
import sys
from common import HTMLTestRunner
from testcase.testSearchPage import TestSearchPage
reload(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ù)組織