基於pytest的主流POM模式——測試框架的設計與實現


1、POM設計模式

——頁面對象模型(Page object Modules),又名:PO/POM,是UI自動化最佳設計模式之一。把一個頁面的測試用例,測試邏輯,封裝為一個測試方法或者一個測試類(說白了,就是把如send_keys、click等方法封裝一下,方便我們調用,后續不需要每次使用時在每次的寫一遍)。

  •  優點:
  1. 測試代碼和頁面的特定代碼(如:定位符、布局)之間有清晰的區分(定位代碼、行為代碼)
  2. 頁面提供的服務或操作只有一個存儲庫(如:類、py文件),不需要把服務分散到整個測試中,集中進行管理,開發或是測試修改時,只需要修改頁面對象就可以了
import pytest
from selenium import webdriver
from time import sleep

class Test_Selenium():
    #環境准備
    @classmethod
    def setup_class(cls):
        cls.driver = webdriver.Chrome()#打開瀏覽器驅動,這樣編寫測試的時長會短,測試損耗的資源也會降低

    def test_baidu_case01(self):
        self.driver.get('http://www.baidu.com')
        sleep(1)
        self.driver.find_element_by_id('kw').send_keys('狗狗幣')
        self.driver.find_element_by_id('su').click()
        sleep(1)
        assert self.driver.title == "狗狗幣_百度搜索" #根據進入的網頁title做斷言

    def test_baidu_case02(self):
        self.driver.get('http://www.baidu.com')
        sleep(1)
        self.driver.find_element('id','kw').send_keys('selenium')
        self.driver.find_element('id','su').click()
        sleep(6)
        assert self.driver.title == "selenium_百度搜索"  # 根據進入的網頁title做斷言

    def test_baidu_case03(self):
        self.driver.get('http://www.baidu.com')
        sleep(2)
        self.driver.find_element_by_id('kw').send_keys('pytest')
        self.driver.find_element_by_id('su').click()
        sleep(1)
        assert self.driver.title == "pytest_百度搜索"  # 根據進入的網頁title做斷言

    #環境清理
    @classmethod
    def teardown_class(cls):
        cls.driver.quit() #退出瀏覽器

if __name__ == '__main__':
    pytest.main(['-s','test_selenium.py'])

 直接使用selenium的原生代碼編寫有2個問題:

  1. 測試用例與自動化用例的定位符(如:百度搜索中的kw、su)之間沒有分開,如果UI更改了屬性值kw、su,所有涉及到這些元素的用例都要改,用例過多時,工作量將會更大
  2. 元素定位代碼將在每個測試用例都需要重復的使用,造成代碼冗余

——這2個問題,使用到POM就可以解決掉。

2、POM涉及模式的編碼實現

目錄:

 base.py——基類,封裝一些常用的方法

from selenium import webdriver
import pytest
import time

class BasePage:
    """
    基礎page層,封裝一些常用的方法
    """

    def __init__(self,driver):
        #導入一下webdriver包,方便后邊代碼的編寫
        self.driver = webdriver.Chrome()

    #打開頁面
    def open(self,url=None):
        if url is None: #如果url沒傳參就會走這里,就會默認進入子類中的url
            self.driver.get(self.url)
        else:
            self.driver.get(url)

    #元素定位
    def locator(self,name,value):#可直接使用8種單數形式的定位方法
        return self.driver.find_element(name,value)

    #獲取title,就是獲取網頁標題欄
    def get_title(self):
        return self.driver.title

    #獲取頁面text,獲取頁面文本,使用xpath定位
    def get_text(self,path):
        return self.locator("xpath",path).text #獲取文本

    #執行JavaScript
    def js(self,script):#腳本作為參數傳進來
        self.driver.execute_script(script)

    #休眠時間(等待時間)
    def sleep(self,sec):
        time.sleep(sec)

 baidu_page.py頁面對象類:

from base import BasePage

"""
baidu_page.py文件是用來存儲百度頁面
"""

#創建BaiduPage類繼承BasePage
class BaiduPage(BasePage):
    #定義url變量,供父類中的open()方法使用
    url = "http://www.baidu.com"

    #文本定位,並輸入關鍵字
    def search_input(self,search_key):
        #使用父類locator方法來定位元素
        #比原生的selenium更加精簡
        self.locator("id","kw").send_keys(search_key)

    #按鈕定位,並點擊
    def search_button(self):
        self.locator("id","su").click()

test_baidu.py

import pytest
from selenium import webdriver
from baidu_page import BaiduPage
from time import sleep


class Test_Baidu():
    # 環境准備
    @classmethod
    def setup_class(cls):
        cls.driver = webdriver.Chrome()

    def test_baidu_search_case01(self):
        page = BaiduPage(self.driver)  # 使用BaiduPage基類,以及繼承的父類的方法,就可以直接使用了
        page.open()  # 在BaiduPage中已經配置url了,這里就不需要配置了
        page.search_input("狗狗幣")
        page.search_button()
        sleep(2)
        assert self.driver.title == "狗狗幣_百度搜索"

    def test_baidu_search_case02(self):
        page = BaiduPage(self.driver)
        page.open()
        page.search_input("selenium")
        page.search_button()
        sleep(2)
        assert self.driver.title == "selenium_百度搜索"

    def test_baidu_search_case03(self):
        page = BaiduPage(self.driver)
        page.open()
        page.search_input("pytest")
        page.search_button()
        sleep(2)
        assert self.driver.title == "pytest_百度搜索"

    # 環境清理
    @classmethod
    def teardown_class(cls):
        cls.driver.quit()  # 退出瀏覽器


if __name__ == '__main__':
    pytest.main(['-s','test_baidu.py'])

結果:

============================= test session starts =============================
platform win32 -- Python 3.8.5, pytest-6.2.5, py-1.10.0, pluggy-1.0.0
rootdir: C:\Users\11130\PycharmProjects\pythonProject2\demo\data
plugins: forked-1.4.0, html-3.1.1, metadata-1.11.0, rerunfailures-10.2, xdist-2.5.0
collected 3 items

test_baidu.py ...

============================= 3 passed in 11.73s ==============================

——使用這樣的方法,我們的代碼將大幅度減少冗余,參數更加的便於管理。


 


免責聲明!

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



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