1、POM設計模式
——頁面對象模型(Page object Modules),又名:PO/POM,是UI自動化最佳設計模式之一。把一個頁面的測試用例,測試邏輯,封裝為一個測試方法或者一個測試類(說白了,就是把如send_keys、click等方法封裝一下,方便我們調用,后續不需要每次使用時在每次的寫一遍)。
- 優點:
- 測試代碼和頁面的特定代碼(如:定位符、布局)之間有清晰的區分(定位代碼、行為代碼)
- 頁面提供的服務或操作只有一個存儲庫(如:類、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個問題:
- 測試用例與自動化用例的定位符(如:百度搜索中的kw、su)之間沒有分開,如果UI更改了屬性值kw、su,所有涉及到這些元素的用例都要改,用例過多時,工作量將會更大
- 元素定位代碼將在每個測試用例都需要重復的使用,造成代碼冗余
——這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 ==============================
——使用這樣的方法,我們的代碼將大幅度減少冗余,參數更加的便於管理。