当前位置:网站首页>PageObject模式解析及案例
PageObject模式解析及案例
2022-07-01 03:28: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
从输出日志来看,每一步操作都清晰可见,出现问题也能快速定位,这些都可以根据实际需要来优化。
边栏推荐
- 389. 找不同
- 【TA-霜狼_may-《百人计划》】2.4 传统经验光照模型
- Binary tree god level traversal: Morris traversal
- 409. 最长回文串
- 8. string conversion integer (ATOI)
- The method to measure the similarity of two vectors: cosine similarity, pytorch calculate cosine similarity: torch nn. CosineSimilarity(dim=1, eps=1e-08)
- 【TA-霜狼_may-《百人计划》】1.2.1 向量基础
- 报错:Plug-ins declaring extensions or extension points must set the singleton directive to true
- 5、【WebGIS实战】软件操作篇——服务发布及权限管理
- [reach out to Party welfare] developer reload system sequence
猜你喜欢

Edlines: a real time line segment detector with a false detection control
![[small sample segmentation] interpretation of the paper: prior guided feature enrichment network for fee shot segmentation](/img/b3/887d3fb64acbf3702814d32e2e6414.png)
[small sample segmentation] interpretation of the paper: prior guided feature enrichment network for fee shot segmentation

bootsrap中的栅格系统

程序员女友给我做了一个疲劳驾驶检测

Error: plug ins declaring extensions or extension points must set the singleton directive to true

AfxMessageBox和MessageBox的用法

IPv4 and IPv6, LAN and WAN, gateway, public IP and private IP, IP address, subnet mask, network segment, network number, host number, network address, host address, and IP segment / number - what does

Idea plug-in backup table

Blueprism registration, download and install -rpa Chapter 1

【TA-霜狼_may-《百人计划》】1.2.2 矩阵计算
随机推荐
报错:Plug-ins declaring extensions or extension points must set the singleton directive to true
4. [WebGIS practice] software operation chapter - data import and processing
208. 实现 Trie (前缀树)
6. zigzag transformation
214. 最短回文串
Edlines: a real time line segment detector with a false detection control
LeetCode 144二叉树的前序遍历、LeetCode 114二叉树展开为链表
【TA-霜狼_may-《百人计划》】2.1 色彩空间
4、【WebGIS实战】软件操作篇——数据导入及处理
[nine day training] content III of the problem solution of leetcode question brushing Report
166. 分数到小数
Leetcode 128 longest continuous sequence (hash set)
FCN full Convolution Network Understanding and Code Implementation (from pytorch Official Implementation)
RSN:Learning to Exploit Long-term Relational Dependencies in Knowledge Graphs
The method to measure the similarity of two vectors: cosine similarity, pytorch calculate cosine similarity: torch nn. CosineSimilarity(dim=1, eps=1e-08)
[深度学习]激活函数(Sigmoid等)、前向传播、反向传播和梯度优化;optimizer.zero_grad(), loss.backward(), optimizer.step()的作用及原理
pytorch训练深度学习网络设置cuda指定的GPU可见
205. 同构字符串
Bilinear upsampling and f.upsample in pytorch_ bilinear
Implement pow (x, n) function