PO設計模式


Page Object Model:

PO設計模式是selenium自動化測試中最佳的設計模式之一,主要體現在對界面交互細節的封裝,也就是在實際測試中只關注業務流程就OK了

傳統的設計中,在新增測試用例之后,代碼會有以下幾個問題:

1.易讀性差:一連串的find element會使代碼顯得雜亂無章

2.可擴展性不好:用例孤立,無法擴展

3.可復用性差:無公共方法,很難復用

4.可維護性差:一旦元素變化,需要維護修改大量測試用例

 

因此考慮到優化:

  PO模式是一種自動化測試設計模式,講頁面定位和業務操作分開,也就是把對象的定位和測試腳本分開,從而提供可維護性。

  首先抽象封裝一個BasePage類,這個基類擁有一些指向Webdriver實例的屬性,然后每一個Page繼承基類BasePage,可以通過driver管理每一個Page中的元素,而且在Page中將這些操作封裝為一個一個的方法。TestCase繼承unittest里面的TestCase類,並且依賴page類,進行組織測試步驟的工作。

  這樣做的好處,就是有元素變化,只需要維護每一個Page就行了,測試步驟變化,只需要維護TestCase即可

 

PO各個核心要素的介紹:

BasePage:

class BasePage(object):
    def __init__(self,driver):
        self.driver = driver

    pass

 

Page:

from SeleniumProject.PO.BasePage import BasePage
class LoginBase(BasePage):
    # 定位元素,括號中是通過find_element來獲取元素的屬性
    uname = ()
    pwd = ()

    def set_uname(self,uname):
        name =self.driver.find_element(*LoginBase.uname)
        name.send_keys("用戶名")
    def set_pwd(self,pwd):
        password = self.driver.find_element(*LoginBase.pwd)
        password.send_keys("密碼")

    pass

TestCase:

from unittest import TestCase
import unittest
from selenium import webdriver
class Test_Login(TestCase):
    def setUp(self):
        self.driver = webdriver.Chrome()
        self.driver.get("https://cn.bing.com/")

    # 測試步驟
    def test_Login(self):
        self.driver.get(self.base_url)
        pass

    def tearDown(self):
        self.driver.quit()

if __name__ == "__main__":
    unittest.main()

 

下面舉一個簡單的例子來看一下PO模式:

  業務要求就是,用Chrome瀏覽器,在https://cn.bing.com/中搜索“墨菲特”,然后點擊搜索按鈕,再關閉瀏覽器

基類BasePage類:

from selenium import webdriver
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC


class BasePage(object):
    """BasePage封裝所有頁面的公有方法,例如url、driver、find_element"""
    # 構造函數里面的參數就是類的所有參數
    def __init__(self,selenuime_driver,base_url):
        self.driver = selenuime_driver
        self.url = base_url

    # 定義一個私有方法,其他類不能調用該方法
    def _open(self,url):
        self.driver.get(url)
        self.driver.maximize_window()

    # 定義open()方法,調用_open()方法
    def open(self):
        self._open(self.base_url)

    # 重寫find_element()方法,參數為任意數量的(帶*的參數)
    # 此方法是為了保證元素是可見的
    def find_emelemt(self,*loc):
        try:
            # 保證元素可見
            WebDriverWait(self.driver,10).until(EC.visibility_of_all_elements_located(loc))
            return self.driver.find_element(*loc)
        except:
            print("頁面中沒有%s %" % (self.loc))

    # 定義script()方法,用於執行JS腳本,比方上上傳文件啥的
    def script(self,src):
        self.driver.excute_script(src)

    # 定義頁面跳轉方法,比方說有的頁面有frame嵌套
    def switch_frame(self,loc):
        return self.driver.switch_to_frame(loc)

    # 重新定義send_keys()方法,為了保證搜索按鈕是否存在,還有有的輸入框中默認有值,要清空
    def send_keys(self,loc,value,clear_first=True,click_first=True):
        try:
            # getattr方法相當於實現了self.loc
            loc = getattr(self,"_%s"%loc)
            # 是否存在搜索按鈕
            if click_first:
                self.find_element(*loc).click()
            # 清空搜索框中的值,並輸入需要搜索的值
            if clear_first:
                self.find_emelemt(*loc).clear()
                self.find_emelemt(*loc).send_keys(value)

        except:
            print("頁面上未找到%s元素"%(self.loc))

Page類:

from selenium.webdriver.common.by import By
from SeleniumProject.PO.BasePage import BasePage

class SearchPage(BasePage):
    # 定位元素
    search_loc = (By.NAME,"q") #搜索框
    btn_loc = (By.NAME,"go")    #搜索按鈕

    # 重寫父類的open()方法
    def open(self):
        self._open(self.base_url)

    def search_content(self,content):
        # 調用父類的find_emelemt,然后將本類的參數傳入
        content1 =  self.find_emelemt(*self.search_loc)
        content1.send_keys(content)

    def btn_click(self):
        btn1 = self.find_emelemt(*self.btn_loc)
        btn1.click()

TestCase類:

from unittest import TestCase
import unittest
from selenium import webdriver
from time import sleep
from SeleniumProject.PO.Search import SearchPage
class CaseRun(TestCase):
    def setUp(self):
        self.driver = webdriver.Chrome()
        sleep(3)
        self.url = "https://cn.bing.com/"
        sleep(3)
        self.content = "墨菲特"
    # 測試步驟
    def test_search(self):
        bing_page = SearchPage(self.driver,self.url)
        bing_page.open()
        sleep(3)
        bing_page.search_content(self.content)
        sleep(3)
        bing_page.btn_click()
        sleep(3)

    def tearDown(self):
        self.driver.quit()

if __name__ == "__main__":
    unittest.main()

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM