当前位置:网站首页>PageObject模式解析及案例
PageObject模式解析及案例
2022-07-01 03:49:00 【覓夢_feng】
一、PO模式:
Page Object(簡稱PO)模式,是Selenium實戰中最為流行,並且是自動化測試中最為熟悉和推崇的一種設計模式。在設計自動化測試時,把頁面元素和元素的操作方法按照頁面抽象出來,分離成一定的對象,然後再進行組織。
做web自動化最頭疼的一個問題,莫過於頁面變化了,如果沒有使用PO設計模式,頁面一變化就意味著之前的元素定比特甚至元素的操作方法不能用了,需要重新修改。你需要一個一個從測試脚本中把需要修改的元素定比特方式、元素的操作方法找出來,然後一一地修改。這樣的自動化脚本不但繁瑣,維護成本也極高。
而page object模式就可以很好地解决這個問題,優點:
减少代碼冗餘
業務和實現分離
降低維護成本
那到底什麼是Page Object模式,見名知意,就是頁面對象,在實際自動化測試中,一般對脚本分為三層:
對象層: 用於存放頁面元素定比特
邏輯層: 用於存放一些封裝好的功能用例模塊
業務層: 用於存放我們真正的測試用例的操作部分
除了以上三層,還有一個基礎層,基礎層主要是針對selenium的一些常用方法,根據實際業務需要進行二次封裝,如點擊、輸入等操作加入一些等待、日志輸入、截圖等操作,方便以後查看脚本的運行情况及問題排查。
二、基礎層:
基礎層類名一般命名為BasePage,後續的對象層操作元素時都繼承這個基礎類,下面以點擊、輸入為例:
# basepage.py
import os
import time
import datetime
from selenium.webdriver.remote.webdriver import WebDriver
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from common.logging import log
from common.constant import IMG_DIR
class BasePage:
def __init__(self, driver: WebDriver):
self.driver = driver
def wait_ele_visible(self, loc, img_desc, timeout=20, frequency=0.5):
"""等待元素可見"""
try:
WebDriverWait(self.driver, timeout, frequency).until(EC.visibility_of_element_located(loc))
log.info("等待:{} - 元素{}可見成功。".format(img_desc, loc))
except:
log.exception("等待:{} - 元素{}可見失敗!".format(img_desc, loc))
self.save_img(img_desc)
raise
def get_element(self, loc, img_desc):
"""查找元素"""
try:
ele = self.driver.find_element(*loc)
except:
log.exception("查找:{} - 元素{}失敗!".format(img_desc, loc))
self.save_img(img_desc)
raise
else:
log.info("查找:{} - 元素{}成功".format(img_desc, loc))
return ele
def click_element(self, loc, img_desc, timeout=20, frequency=0.5):
"""點擊元素"""
self.wait_ele_visible(loc, img_desc, timeout, frequency)
ele = self.get_element(loc, img_desc)
try:
ele.click()
log.info("點擊:{} - 元素{}成功".format(img_desc, loc))
except:
log.exception("點擊:{} - 元素{}失敗!".format(img_desc, loc))
self.save_img(img_desc)
raise
def input_text(self, loc, value, img_desc, timeout=20, frequency=0.5):
"""在元素中輸入文本"""
self.wait_ele_visible(loc, img_desc, timeout, frequency)
ele = self.get_element(loc, img_desc)
try:
ele.send_keys(value)
log.info("輸入:在{} - 元素{}輸入文本值({})成功".format(img_desc, loc, value))
except:
log.exception("輸入:在{} - 元素{}輸入文本值({})失敗!".format(img_desc, loc, value))
self.save_img(img_desc)
raise
def save_img(self, img_description):
"""保存异常截圖"""
now = time.strftime("%Y-%m-%d %H-%M-%S ", time.localtime())
img_path = os.path.join(IMG_DIR, now + img_description + '.png')
try:
self.driver.save_screenshot(img_path)
except:
log.exception("异常截圖失敗!")
else:
log.info("异常截圖成功,截圖存放在{}".format(img_path))
以點擊click_element()為例,這裏二次封裝時加入了等待操作、日志輸入、异常截圖,後面點擊元素時就直接調用click_element()就可以一步到比特,不需要再考慮等待、日志、异常的情况,這裏都已經處理好了,雖然在初期寫基礎頁面會比較耗時,但只要基礎打好,在後續維護工作中會輕松很多。以上只是一個示例,可以根據自己的實際需要進行優化。
三、對象層、邏輯層:
對象層存放頁面元素定比特,邏輯層存放元素操作方法(頁面功能),元素定比特可以根據實際需要,可以單獨放在一個模塊來維護,也可以存放在excel中進行集中管理;下面演示的是元素定比特和元素操作方法都存放到一個模塊中,一個頁面一個模塊,後續頁面元素發生變化,只需要修改在這個模塊中修改對應的定比特錶達式或者操作方法即可。
演示以百度首頁為例:
# baidu_page.py
from selenium.webdriver.common.by import By
from common.basepage import BasePage
class LoginPage(BasePage):
login_btn = (By.XPATH, '//div[@id="u1"]//a[@name="tj_login"]') # 登錄按鈕
username_login_btn = (By.ID, 'TANGRAM__PSP_11__footerULoginBtn') # 用戶名登錄按鈕
user_input = (By.ID, 'TANGRAM__PSP_11__userName') # 用戶信息輸入框
pwd_input = (By.ID, 'TANGRAM__PSP_11__password') # 密碼輸入框
login_submit = (By.ID, 'TANGRAM__PSP_11__submit') # 登錄提交按鈕
def login(self, user, pwd):
""" 百度用戶名登錄 :param user: 手機/郵箱/用戶名 :param pwd: 密碼 :return: """
self.click_element(self.login_btn, '百度-登錄')
self.click_element(self.username_login_btn, '百度登錄-用戶名登錄')
self.input_text(self.user_input, user, '用戶名登錄-手機/郵箱/用戶名')
self.input_text(self.pwd_input, pwd, '用戶名登錄-密碼')
self.click_element(self.login_submit, '用戶名登錄-登錄')
四、業務層:
用於存放真正的測試用例操作,這裏不會出現元素定比特、頁面功能,所有操作都是直接調用邏輯層的.
測試用例 = 測試對象的功能 + 測試數據,下面以百度登錄為例(用於演示,簡略寫的):
import unittest
import pytest
import ddt
from selenium import webdriver
from PageObjects.baidu_login_page import LoginPage
from testdatas import common_datas as com_d
from testdatas import login_data as lo_d
from common.logging import log
@ddt.ddt
class TestLogin(unittest.TestCase):
def setUp(self):
log.info("-------用例前置工作:打開瀏覽器--------")
self.driver = webdriver.Chrome()
self.driver.get(com_d.baidu_url)
self.driver.maximize_window()
def tearDown(self):
self.driver.quit()
log.info("-------用例後置工作:關閉瀏覽器--------")
@pytest.mark.smoke
def test_login_success(self):
# 用例:登錄頁的登錄功能
# 步驟
LoginPage(self.driver).login(lo_d.success_data['user'], lo_d.success_data['pwd'])
# 斷言.....
五、運行結果:
Testing started at 11:50 ...
D:\python\python.exe "D:JetBrains\PyCharm Community Edition 2019.1.3\helpers\pycharm\_jb_unittest_runner.py" --path D:/learn/test/testcases/test_baidu_login.py
Launching unittests with arguments python -m unittest D:/learn/test/testcases/test_baidu_login.py in D:\learn\test\testcases
Process finished with exit code 0
2021-03-14 11:50:47,238-【test_baidu_login.py-->line:27】-INFO:-------用例前置工作:打開瀏覽器--------
2021-03-14 11:50:51,327-【basepage.py-->line:38】-INFO:等待:百度-登錄 - 元素('xpath', '//div[@id="u1"]//a[@name="tj_login"]')可見成功,耗時0:00:00.056843秒
2021-03-14 11:50:51,339-【basepage.py-->line:77】-INFO:查找:百度-登錄 - 元素('xpath', '//div[@id="u1"]//a[@name="tj_login"]')成功
2021-03-14 11:50:51,414-【basepage.py-->line:86】-INFO:點擊:百度-登錄 - 元素('xpath', '//div[@id="u1"]//a[@name="tj_login"]')成功
2021-03-14 11:50:53,463-【basepage.py-->line:38】-INFO:等待:百度登錄-用戶名登錄 - 元素('id', 'TANGRAM__PSP_11__footerULoginBtn')可見成功,耗時0:00:02.048293秒
2021-03-14 11:50:53,474-【basepage.py-->line:77】-INFO:查找:百度登錄-用戶名登錄 - 元素('id', 'TANGRAM__PSP_11__footerULoginBtn')成功
2021-03-14 11:50:53,535-【basepage.py-->line:86】-INFO:點擊:百度登錄-用戶名登錄 - 元素('id', 'TANGRAM__PSP_11__footerULoginBtn')成功
2021-03-14 11:50:53,576-【basepage.py-->line:38】-INFO:等待:用戶名登錄-手機/郵箱/用戶名 - 元素('id', 'TANGRAM__PSP_11__userName')可見成功,耗時0:00:00.040890秒
2021-03-14 11:50:53,584-【basepage.py-->line:77】-INFO:查找:用戶名登錄-手機/郵箱/用戶名 - 元素('id', 'TANGRAM__PSP_11__userName')成功
2021-03-14 11:50:53,714-【basepage.py-->line:98】-INFO:輸入:在用戶名登錄-手機/郵箱/用戶名 - 元素('id', 'TANGRAM__PSP_11__userName')輸入文本值(15692004245)成功
2021-03-14 11:50:53,759-【basepage.py-->line:38】-INFO:等待:用戶名登錄-密碼 - 元素('id', 'TANGRAM__PSP_11__password')可見成功,耗時0:00:00.043882秒
2021-03-14 11:50:53,771-【basepage.py-->line:77】-INFO:查找:用戶名登錄-密碼 - 元素('id', 'TANGRAM__PSP_11__password')成功
2021-03-14 11:50:53,925-【basepage.py-->line:98】-INFO:輸入:在用戶名登錄-密碼 - 元素('id', 'TANGRAM__PSP_11__password')輸入文本值(phang0209)成功
2021-03-14 11:50:53,958-【basepage.py-->line:38】-INFO:等待:用戶名登錄-登錄 - 元素('id', 'TANGRAM__PSP_11__submit')可見成功,耗時0:00:00.031914秒
2021-03-14 11:50:53,969-【basepage.py-->line:77】-INFO:查找:用戶名登錄-登錄 - 元素('id', 'TANGRAM__PSP_11__submit')成功
2021-03-14 11:50:54,051-【basepage.py-->line:86】-INFO:點擊:用戶名登錄-登錄 - 元素('id', 'TANGRAM__PSP_11__submit')成功
2021-03-14 11:50:56,426-【test_baidu_login.py-->line:35】-INFO:-------用例後置工作:關閉瀏覽器--------
Ran 1 test in 9.191s
OK
從輸出日志來看,每一步操作都清晰可見,出現問題也能快速定比特,這些都可以根據實際需要來優化。
边栏推荐
- Explain spark operation mode in detail (local+standalone+yarn)
- [party benefits] jsonobject to string, leave blank
- Quickly filter data such as clock in time and date: Excel filter to find whether a certain time point is within a certain time period
- Test function in pychram
- 392. judgment subsequence
- pytorch nn. AdaptiveAvgPool2d(1)
- jeecgboot输出日志,@Slf4j的使用方法
- [TA frost wolf \u may- hundred people plan] 1.3 secret of texture
- MFC窗口滚动条用法
- [EI conference] the Third International Conference on nanomaterials and nanotechnology in 2022 (nanomt 2022)
猜你喜欢

jeecgboot输出日志,@Slf4j的使用方法

整合阿里云短信的问题:无法从静态上下文中引用非静态方法

详解Spark运行模式(local+standalone+yarn)

Pytorch training deep learning network settings CUDA specified GPU visible

pytorch nn. AdaptiveAvgPool2d(1)

Feature Pyramid Networks for Object Detection论文理解

Jeecgboot output log, how to use @slf4j

Appium fundamentals of automated testing - basic principles of appium

Use selenium automated test tool to climb the enrollment score line and ranking of colleges and universities related to the college entrance examination

431. encode n-ary tree as binary tree DFS
随机推荐
Grid system in bootstrap
Idea plug-in backup table
[party benefits] jsonobject to string, leave blank
318. 最大单词长度乘积
Jeecgboot output log, how to use @slf4j
[深度学习]激活函数(Sigmoid等)、前向传播、反向传播和梯度优化;optimizer.zero_grad(), loss.backward(), optimizer.step()的作用及原理
LeetCode 31下一个排列、LeetCode 64最小路径和、LeetCode 62不同路径、LeetCode 78子集、LeetCode 33搜索旋转排序数组(修改二分法)
[reach out to Party welfare] developer reload system sequence
Its appearance makes competitors tremble. Interpretation of Sony vision-s 02 products
Error: plug ins declaring extensions or extension points must set the singleton directive to true
72. 编辑距离
衡量两个向量相似度的方法:余弦相似度、pytorch 求余弦相似度:torch.nn.CosineSimilarity(dim=1, eps=1e-08)
ASGNet论文和代码解读2
Leetcode: offer 59 - I. maximum value of sliding window
[EI conference] 2022 international joint civil and Offshore Engineering Conference (jccme 2022)
242. 有效的字母异位词
Use selenium automated test tool to climb the enrollment score line and ranking of colleges and universities related to the college entrance examination
409. 最长回文串
187. 重复的DNA序列
214. 最短回文串