web自動化之PO模式

PO模式

1、為什么需要PO思想?

首先我們觀察和思考一下,目前我們寫的作業腳本的問題: 元素定位和操作動 作寫到一起了,這就就會用導致一個問題:

  • UI的頁面元素比較容易變化的,所以元素定位和腳本操作寫到一起,一旦 元素發生了變化,這些腳本都需要修改
  • 特別是登錄頁面在很多個頁面都會涉及到 被引用,那么就會導致: 維護成 本比較大。 所以,我們通過PO模式來解決這個問題。

2、什么是PO模式

Page Object Model(頁面對象模型), 或者也可稱之為POM。在UI自動化測試 廣泛使用的一種分層設計模式。

page就是網頁的頁面層,object就是封裝的LoginPage 類:每一個頁面一個 類,包含業務邏輯和測試對象

  • 頁面元素元素定位: 定義為類的屬性
  • 頁面的操作行為 : 定義為類的方法
  • 業務邏輯: 對頁面的操作 為了得到實際結果的過程 和步驟 ,這是測試 對象

測試用例+ 測試數據層: 單獨維護。 包含測試邏輯步驟和測試用例

  • 測試邏輯: 測試部分 ,預期結果和實際結果的對比 ,這是測試用例

PO核心是通過頁面層封裝所有的頁面元素及操作,測試用例層通過調用頁面層 操作組裝業務邏輯。

PO模式的核心思想:體現了業務邏輯和測試邏輯?的分離,測試用例和測試對象分離

以登錄操作為例:

  • 獲取頁面登錄錯誤信息 登出 等操作都是業務邏輯,單獨進行PageObject 的封裝。
  • 用例里只傳用例數據,不會出現元素定位的代碼。包括斷言里也不要出現 元素定位。

PO模式最終的實現效果:

頁面層:

  • 頁面類A(A1 A2 A3)
  • 頁面類B(B1 B2 B3) 頁面類C(C1 C2 C3)

用例層:

  • 用例1 = A1 + B2 + C3
  • 用例2 = A1 + B2 + C1

PO模式優點:

  • 提高測試用例的可讀性
  • 提高測試用例可維護性
  • 減少代碼重復

我們現在以登錄頁面為例:登錄頁面類

因為這個頁面里有元素定位 + 元素操作: 把這些東西最好是封裝在一起,方便 被用例層調用。

  • 頁面里的元素: 寫成類的屬性
    • 用元組形式表示;因為后面顯示等待都是用元組調用的;調用用self調 用 ;
    • 并不需要一次性把所有元素都寫出來,可以后續擴展
  • 頁面的操作: 封裝成實例方法
    • driver先沒有,
    • 可以作為參數 一些變化的數據也參數化

三層PO思想【BasePage封裝思想】

但是這樣寫還有個問題:既然每個元素都用顯示等待操作,每個頁面都寫一 遍太麻煩,冗余度太高了;而且每個頁面都有一些其他的共同的操作,比如點 擊,輸入文本等;那么每個頁面都重復寫,是不是可以進一步優化呢?

  • 這些每個頁面都會調用的方法【等待,點擊,輸入文本等】,就屬于公共 方法; BasePage 封裝思想
  • 用三層PO模式: 公共頁面的內容單獨提取出來封裝:這也叫做 。封裝成為一個BasePage類。
  • 其他頁面自己獨有的元素和方法依然放在單獨頁面類里封裝;需要用到 basepage類的內容的時候,如何實現?--- 類的繼承實現

所以新建一個common的目錄,建一個base_page的py文件,方所有的功能 方法。

  • BasePage 用來存放所有頁面類的公共部分,一些公共的操作(顯式封裝)
  • 封裝一個BasePage的類,里面的方法都是每個頁面都要用的公共的方法。

base_page.py
from time import sleepimport pyautogui
import pyperclip
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.common.action_chains import ActionChainsclass BasePage:# driver每個方法都用,如果直接定位參數,沒有辦法實現實例方法共享,所以可以定義為實例屬性 實現共享def __init__(self,driver): # 初始化方法里定義了以參數  到時候實例化對象傳參"""初始化函數 定義driver作為實例屬性 實例實例方法共享這個實例屬性"""self.driver = driver# 操作和行為 行為為實例方法def wait_element_clickable(self, locator):web_element = WebDriverWait(self.driver, 8, 0.5).until(EC.element_to_be_clickable(locator))return web_elementdef wait_element_visible(self, locator):web_element = WebDriverWait(self.driver, 8, 0.5).until(EC.visibility_of_element_located(locator))return web_elementdef wait_element_presence(self, locator):web_element = WebDriverWait(self.driver, 8, 0.5).until(EC.presence_of_element_located(locator))return web_element# 1、普通點擊操作 --關鍵字def click_element(self,locator):self.wait_element_clickable(locator).click()# 2、鼠標點擊操作def mouse_click(self,locator):# 先找到元素element = self.wait_element_visible(locator)# 用鼠標點擊ActionChains(self.driver).click(element).perform()# 3、js點擊操作def js_click(self,locator):# 先找到元素element = self.wait_element_visible(locator)# 用js傳參點擊self.driver.execute_script("arguments[0].click()",element)# 4、輸入數據文本def input_text(self,locator,text):self.wait_element_visible(locator).send_keys(text)# 5、獲取元素的文本 : 拿到這個文本 返回這個文本def get_text(self,locator):return self.wait_element_visible(locator).text# 6、獲取元素的屬性:拿到這個屬性的值 設置為返回值def get_attribute(self,locator,attr_name):return self.wait_element_visible(locator).get_attribute(attr_name)# 7、窗口切換def switch_window(self,url):# 先拿到所有的窗口句柄handles = self.driver.window_handlesfor win in handles:if self.driver.current_url == url:  # 判斷當前的頁面是否為想要的url地址breakelse:self.driver.switch_to.window(win)  # 如果不是 繼續切換# 8、移動鼠標def move_mouse(self,locator):element = self.wait_element_presence(locator)ActionChains(self.driver).move_to_element(element).perform()# 9、文件上傳def file_upload(self,file_path):# 1、先復制路徑pyperclip.copy(file_path)# 2、粘貼 -- hotkey 通過熱鍵粘貼pyautogui.hotkey("ctrl", "v")pyautogui.press("enter", presses=2)
home_page_v1.py
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWaitclass HomePage:# 頁面元素元素定位: 定義為類的屬性 --元組loc_login = (By.XPATH, '//a[text()="登錄"]')# 操作和行為 行為為實例方法def wait_element_clickable(self,driver,locator):web_element = WebDriverWait(driver, 8, 0.5).until(EC.element_to_be_clickable(locator))return web_elementdef wait_element_visible(self,driver,locator):web_element = WebDriverWait(driver, 8, 0.5).until(EC.visibility_of_element_located(locator))return web_elementdef wait_element_presence(self,driver,locator):web_element = WebDriverWait(driver, 8, 0.5).until(EC.presence_of_element_located(locator))return web_element# 點擊首頁里的登錄鏈接按鈕 打開登錄頁面 操作-- 定義為實例方法def click_login_link(self,driver):self.wait_element_visible(driver,self.loc_login).click()
test_login.py
"""
編寫測試用例 執行測試用例 斷言 的框架 - pytest框架
"""
from page_object.login_page_v1 import LoginPage
from page_object.home_page_v1 import HomePage
from selenium import webdriver# pytest框架編寫測試用例
def test_login():driver = webdriver.Chrome()driver.maximize_window()driver.get("http://mall.lemonban.com:3344/")# 1、點擊homepage 登錄的鏈接 == 先實例化對象,再調用實例方法,實例方法要傳參driverHomePage().click_login_link(driver)# 2、調用LoginPage里的login實例方法  執行登錄操作== 先實例化對象,再調用實例方法,實例方法要傳參LoginPage().login(driver,"lemon_py","12345678")

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/14594.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/14594.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/14594.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

如何將照片從 iPhone 傳輸到閃存驅動器【無質量損壞】

概括 人們喜歡用 iPhone 拍照,因為照片通常都很漂亮,這都要歸功于 iPhone 令人驚嘆的技術。但照片更新后會占用更多空間,并且您可能會開始收到沒有存儲空間的通知。因此,您可以將照片傳輸到 USB 驅動器,然后從 iPhone…

Spring Boot構建mvc項目

好的,以下是一個簡單的Java MVC(Model-View-Controller)項目示例,使用Spring Boot框架和MySQL數據庫。這個項目包括基本的CRUD操作。 項目結構 src/ └── main/├── java/│ └── com/│ └── example/│ └── demo/│ ├──…

springboot-阿里羚羊 服務端埋點

官方文檔 集成Java SDK 手動引入jar包「quickaplus-log-collector-java-sdk-1.0.1-SNAPSHOT.jar」 <dependency><groupId>com.alibaba.lingyang</groupId><artifactId>quickaplus-log-collector-java-sdk</artifactId><version>1.0.1&l…

應用案例 | 如何實時監測和管理冷鏈倉庫溫濕度?

一、項目背景 冷鏈倉庫溫濕度管理的重要性在于確保倉庫內產品的質量和安全。通過遵循相關法規和標準&#xff0c;滿足客戶對產品質量的需求&#xff0c;同時實施有效的溫濕度管理措施&#xff0c;可以降低成本并提高倉庫作業效率。該項目的實施旨在幫助客戶保證產品的新鮮度&a…

Java - AbstractQueuedSynchronizer

AQS簡介 AQS全稱AbstractQueuedSynchronizer&#xff0c;抽象隊列同步器&#xff0c;是一個實現同步組件的基礎框架。AQS使用一個int類型的成員變量state維護同步狀態&#xff0c;通過內置的同步隊列&#xff08;CLH鎖、FIFO&#xff09;完成線程的排隊工作&#xff0c;底層主…

echarts 散點圖修改散點圖中圖形形狀顏色大小

話不多說&#xff0c;直接上代碼 let option {color:[xxx, xxx, xxx, xxx], //直接設置color可修改圖形顏色title: {text: 散點圖圖形,},tooltip: {trigger: axis,axisPointer: {type: cross}},legend: {top: 2,right:2,itemWidth: 10,itemHeight: 10,textStyle:{fontSize:14}…

shell腳本條件語句和循環語句

文章目錄 一、條件語句測試比較整數數值字符串比較邏輯運算雙中括號&#xff08; &#xff09;{ }if語句結構case語句 二、循環語句基礎知識for循環whileuntil雙重循環及跳出循環 一、條件語句 測試 條件測試&#xff1a;判斷某需求是否滿足&#xff0c;需要由測試機制來實現…

視頻分類——C3D使用

整體比較分散&#xff0c;可能很多源碼都需要修改&#xff0c;需要有耐心。 一、數據準備 PS 調研后&#xff0c;上手容易代碼比較簡潔的是&#xff1a;https://github.com/Niki173/C3D/tree/main 因為源碼很多參數都寫死到了源碼中&#xff0c;沒有解耦&#xff0c;并且默…

CCF-CSP認證 2024年3月 4.化學方程式配平

題解&#xff1a;首先完成數據的讀入&#xff0c;然后高斯消元求秩按題意解即可 #pragma GCC optimize(2, 3, "Ofast", "inline") #include <bits/stdc.h> using namespace std; const int maxn 100;using matrix double[maxn][maxn]; using vect…

5.20Git

版本控制工具Git&#xff0c;其他的工具還有SVN 共享代碼&#xff0c;追溯記錄&#xff0c;存儲.c文件 Git實現的功能&#xff1a;回溯&#xff08;以前某個時間節點的數據情況&#xff09;共享&#xff08;大家共享修改&#xff09; Git&#xff1a;80% SVN&#xff…

QT tableWidget詳細分析

一.定義 QTableWidget是一個用于顯示表格數據的Qt控件&#xff0c;它是一個基于Qt Model/View框架的視圖組件。QTableWidget提供了一種簡單的方式來展示和編輯表格數據&#xff0c;用戶可以通過添加行、列和單元格來構建一個完整的數據表格。 下面是一些QTableWidget的主要特點…

The Missing Semester of Your CS Education(計算機教育中缺失的一課)

Shell 工具和腳本(Shell Tools and Scripting) 一、shell腳本 1.1、變量賦值 在bash中為變量賦值的語法是foobar&#xff0c;訪問變量中存儲的數值&#xff0c;其語法為 $foo。 需要注意的是&#xff0c;foo bar &#xff08;使用空格隔開&#xff09;是不能正確工作的&…

網工內推 | 香港移動,10年以上數通經驗,CCIE,5W-6W

01 香港移動招聘 &#x1f537;招聘崗位&#xff1a;網絡工程師 &#x1f537;崗位要求&#xff1a; 需要有10年及以上數通經驗&#xff0c;有CCIE 證書&#xff0c;懂技術管理&#xff0c;溝通暢通 &#x1f537;語言要求&#xff1a; 粵語英語 &#x1f537;薪資&#xff1…

基于灰狼優化算法優化RBF(GWO-RBF)的數據回歸預測(多輸入多輸出)

代碼原理及流程 基于灰狼優化算法優化多輸入多輸出&#xff08;MIMO&#xff09;的RBF神經網絡的數據回歸預測&#xff0c;可以采取以下步驟&#xff1a; 1. 數據準備&#xff1a;準備包含多個輸入特征和多個輸出目標的數據集&#xff0c;確保數據已經經過預處理和歸一化。 …

TCP - 半連接隊列和全連接隊列

目錄 一、半連接隊列和全連接隊列的概念 二、全連接隊列溢出 三、半連接隊列溢出 一、半連接隊列和全連接隊列的概念 1. 半連接隊列&#xff1a;服務端收到客戶端發送的 SYN 包時&#xff0c;內核會將該連接加入半連接 SYN 隊列&#xff0c;并向客戶端返回響應 2. 全連接隊…

CSS基礎(第二天)

Emmet語法 快速生成HTML結構語法 1. 生成標簽 直接輸入標簽名 按tab鍵即可 比如 div 然后tab 鍵&#xff0c; 就可以生成 <div></div> 2. 如果想要生成多個相同標簽 加上 * 就可以了 比如 div*3 就可以快速生成3個div 3. 如果有父子級關系的標簽&#xff0c;可以…

算法刷題筆記 數的范圍(C++實現)(二分法重要例題)

文章目錄 題目描述題目思路題目代碼&#xff08;C&#xff09;題目感想 題目描述 給定一個按照升序排列的長度為n的整數數組&#xff0c;以及q個查詢。對于每個查詢&#xff0c;返回一個元素k的起始位置和終止位置&#xff08;位置從0開始計數&#xff09;。如果數組中不存在該…

Docker【2】iptables 錯誤解決

iptables 錯誤解決 問題說明問題分析解決步驟1. 確保 iptables 模塊已加載2. 檢查和重啟 docker 服務3. 檢查 firewalld 狀態4. 重置 iptables 規則5. 查看和更新 Docker 配置 總結 問題說明 執行的 docker 命令如下&#xff0c;啟動 nginx 并設置宿主機端口 (8080) 與容器端口…

學習Uni-app開發小程序Day25

這一章學習了觸底加載更多阻止無效的網絡請求、分類列表存入Storage在預覽頁面讀取緩存展示、通過swiper的事件實現真正的壁紙預覽及切換 觸底加載更多阻止無效的網絡請求、load-more樣式的展現 前面已經學習了當列表觸底后&#xff0c;會繼續加載&#xff0c;當到最后一層后…

自動化測試--利用pytest實現整條業務鏈路測試

? 概述 前面一章講解了單個接口的測試&#xff0c;但是實際項目中&#xff0c;因為權限和登錄狀態的限制&#xff0c;大部分接口沒辦法直接訪問到&#xff0c;這時候我們想訪問到一個系統的接口&#xff0c;就需要模擬用戶登錄拿到用戶的token和所擁有的權限之后再將這些信息…