1. 程式人生 > 其它 >UI自動化測試之頁面物件設計模式

UI自動化測試之頁面物件設計模式

1、概述

1.1頁面物件設計模式的優勢

頁面物件設計模式(page object)又叫po模式,PO模式是一種自動化測試設計模式,將頁面定位和業務操作分開,也就是把物件定位和測試指令碼分開,從而提供可維護性。核心思想是通過對介面元素的封裝減少冗餘程式碼,主要體現在對介面互動細節的封裝,也就是在實際測試中只關注業務流程;同時在後期維護中,若元素定位發生變化, 只需要調整頁面元素封裝的程式碼,提高測試用例的可維護性、可讀性。在自動化測試過程中,對於維護的成本而言,需要考慮進一步的優化,那麼我們可以使用頁面物件設計模式,它的具體優勢如下:

(1)建立可以跨多個測試用例共享的程式碼

(2)減少重複程式碼的數量

(3)如果使用者介面發生了維護,我們只需要維護一個地方,這樣修改以及維護的成本相對而言是比較低的。

1.2建立專案

在pycharm中建立專案的步驟如圖:

 

 然後點選attch即可在project中看到新建立的專案:

 

 給已經建立好的專案配置python直譯器:

 2、頁面物件設計

2.1目錄結構設計

編寫的目錄順序可自行調整,如下圖:

各個目錄詳解:

(1)base:基礎層,主要編寫底層定位元素的類,它是一個包。

(2)common:公共類,裡面編寫公共使用到的方法。

(3)config:配置檔案儲存目錄。

(4)data:儲存測試使用到測試資料。

(5)page:物件層,編寫具體的業務邏輯,把頁面每一個操作行為單獨的寫一個方法或者是函式。

(6)report:測試報告目錄,主要用來存放測試報告。

(7)test:測試層,裡面主要是測試模組,也可以說是每個測試的場景的程式碼。

(8)utils:工具類,存放工具,如說明文件等。

2.2具體頁面設計模式

這裡以新浪郵箱為例,來說明整個頁面設計的具體目錄如何實現的程式碼。

2.2.1基礎層:base

基礎層,主要編寫底層定位元素的類,它是一個包;元素定位有兩類,單個元素定位和多個元素定位。以及一種特殊的情況,定位iframe框架中的元素,我們之前已經說過,進入iframe框架有三種方式:ID、name和索引,這裡簡述通過ID進入iframe框架的方式:

#base:基礎層,主要編寫底層定位元素的類,它是一個包;元素定位有兩類,單個元素定位和多個元素定位,還有一種特殊情況,即需要定位的元素在iframe框架中。
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.expected_conditions import NoSuchElementException
import time
#定義一個編寫底層定位元素的類
class WebUI(object):
	def __init__(self,driver):
#=driver裡的drive可以理解為webdriver例項化後的物件,這裡只是做一個假設,在測試類中進行驗證,
		self.driver=driver

		'''單個元素定位的方式
			args:*args:識別元素屬性,ctr+滑鼠放置到元素+左鍵:判斷定位元素屬性的方法是否正確
			:return:它是一個元組,需要帶上具體什麼方式定位元素屬性以及元素屬性的值'''

#單個元素定位:
	# def findElement(self,*args):
	# 	return self.driver.find_element(*args)

	# 如果想要獲取到執行異常是的詳細資訊,可以使用函式異常邏輯,except返回具體錯誤資訊。
	def findElement(self,*args):
		try:
			return self.driver.find_element(*args)
		except NoSuchElementException as e:
			return e.args[0]

		'''單個元素定位的方式
			args:*args:識別元素屬性,ctr+滑鼠放置到元素+左鍵:判斷定位元素屬性的方法是否正確
			index:識別元素的索引
			:return:它是一個元組,需要帶上具體什麼方式定位元素屬性以及元素屬性的值'''

# #多個元素定位,由於需要使用到他的索引,所以需要加一個index引數。
# 	def findElements(self, *args, index):
# 		return self.driver.find_elements(*args)[index]

# 如果想要獲取到執行異常是的詳細資訊,可以使用函式異常邏輯,except返回具體錯誤資訊。
	def findElements(self,*args,index):
		try:
			return self.driver.find_elements(*args)[index]
		except NoSuchElementException as e:
			return e.args[0]

#iframe框架中的元素定位,這裡簡述通過ID的方式進入iframe框架:
	def findFrame(self,frameID):
		return self.driver.switch_to.frame(frameID)

2.2.2物件層:page

物件層,編寫具體的業務邏輯,把頁面每一個操作行為單獨的寫一個方法或者是函式,他是一個包。

#page:物件層,編寫具體的業務邏輯,把頁面每一個操作行為單獨的寫一個方法或者是函式。如下:
from selenium.webdriver.common.by import By
from base.base import WebUI
import time
#定義一個登入的類:username、password、loginEnter、errorPrompt是登入的類中的資料屬性,可以在整個類中呼叫,呼叫的方式為:self.資料屬性。
class Login(WebUI):
	username=(By.ID,"freename")
	password=(By.ID,"freepassword")
	loginEnter=(By.CLASS_NAME,"loginBtn")
	errorPrompt=(By.XPATH,"/html/body/div[3]/div/div[2]/div/div/div[4]/div[1]/div[1]/div[1]/span[1]")

#使用者名稱:輸入使用者名稱這個操作的函式
	def InputUsername(self,username):
		time.sleep(3)
		self.findElement(*self.username).send_keys(username)

#密碼:輸入密碼這個操作的函式
	def InputPassword(self,password):
		time.sleep(3)
		self.findElement(*self.password).send_keys(password)

#點選登陸這個操作的函式
	def loginClick(self):
		self.findElement(*self.loginEnter).click()

#獲取提示框文字資訊的函式
	def textInformation(self):
		return self.findElement(*self.errorPrompt).text

#封裝:把新浪輸入使用者名稱和密碼後點擊登入的操作封裝為一個函式。
	def sinaLogin(self,username,password):
		self.InputUsername(username=username)
		self.InputPassword(password=password)
		self.loginClick()

2.2.3測試層:test

測試層,裡面主要是測試模組,也可以說是每個測試的場景的程式碼。

#test:測試層,裡面主要是測試模組,也可以說是每個測試的場景的程式碼。
from selenium import webdriver
import unittest
from page.login import Login
import time
#定義一個測試類:
class UnitTest(unittest.TestCase,Login):
#初始化
	def setUp(self) -> None:
		self.driver=webdriver.Chrome()    #這裡是對webdriver進行例項化,也是對基礎層中driver假設的證明。
		self.driver.maximize_window()
		self.driver.get("https://mail.sina.com.cn/")
		self.driver.implicitly_wait(30)
#清理
	def tearDown(self) -> None:
		self.driver.quit()

#測試模組:登陸的使用者名稱和密碼為空
	def test_login_Empty(self):    #測試用例的名稱一定要以test開頭,推薦test_。
		self.InputUsername(username="")   #呼叫page中的輸入使用者名稱的函式
		self.InputPassword(password="")   #呼叫page中的輸入密碼的函式
		self.loginClick()     #呼叫page中點選登入的函式
		# self.sinaLogin(username="",password="")     #呼叫在page中封裝的函式sinaLogin()。
		time.sleep(5)
		self.assertEqual(self.textInformation(),"請輸入郵箱名")    #斷言,驗證登入提示的文字資訊,呼叫page中的獲取提示框文字資訊的函式
		time.sleep(5)

#測試模組:登陸的使用者名稱和密碼格式不對
	def test_login_format(self):    #測試用例的名稱一定要以test開頭,推薦test_。
		self.InputUsername(username="asd123")      #呼叫page中的輸入使用者名稱的函式
		self.InputPassword(password="asd123")     #呼叫page中的輸入密碼的函式
		self.loginClick()     #呼叫page中點選登入的函式
		# self.sinaLogin(username="asd123",password="asd123")    #呼叫在page中封裝的函式sinaLogin()。
		time.sleep(5)
		self.assertEqual(self.textInformation(),"您輸入的郵箱名格式不正確")    ##斷言,驗證登入提示的文字資訊,呼叫page中的獲取提示框文字資訊的函式
		time.sleep(5)

#測試模組:登陸的使用者名稱和密碼錯誤
	def test_login_error(self):    #測試用例的名稱一定要以test開頭,推薦test_。   #呼叫在page中封裝的函式sinaLogin()。
		self.InputUsername(username="[email protected]")    #呼叫page中的輸入使用者名稱的函式
		self.InputPassword(password="asd123")     #呼叫page中的輸入密碼的函式
		self.loginClick()     #呼叫page中點選登入的函式
		# self.sinaLogin(username="[email protected]",password="asd123")
		time.sleep(5)
		self.assertEqual(self.textInformation(),"登入名或密碼錯誤")     ##斷言,驗證登入提示的文字資訊,呼叫page中的獲取提示框文字資訊的函式
		time.sleep(5)