Selenium page object模式Python

目录

概述

优点

示例

项目结构:

基础页面类BasePage

业务页面类BaiduHomePage

测试类test_baidu:

文件工具类file_util

运行日志:

测试结果:


概述

在web应用程序的UI中,有一些区域可以与测试交互。页面对象仅将这些对象建模为测试代码中的对象。这减少了重复代码的数量,意味着如果UI发生更改,则只需在一个位置应用修复。

页面对象是一种在测试自动化中流行的设计模式,用于增强测试维护和减少代码重复。页面对象是一个面向对象的类,用作AUT页面的接口。然后,每当需要与该页面的UI交互时,测试就会使用该页面对象类的方法。好处是,如果页面的UI发生了更改,则测试本身不需要更改,只需要更改页面对象中的代码。随后,所有支持新UI的更改都位于同一位置。

优点

测试代码和特定于页面的代码之间有一个清晰的分离,例如定位器(或者如果您使用的是UI映射,则使用它们)和布局。

  • 页面提供的服务或操作只有一个存储库,而不是将这些服务分散在整个测试中。
  • 在这两种情况下,这都允许在一个地方进行由于UI更改而需要的任何修改。

示例

演示一个百度搜索功能搜索关键字selenium并做断言,然后保存断言结果截图到对应日期文件夹。

项目结构:

基础页面类BasePage

封装页面基本操作,主要是跟业务不相关的公共方法,如:元素查找、点击、文本输入、截图、双击、获取元素坐标等,跟页面相关的方法不建议封装在基础页面类中,以下是一个简单的实例:

import logging
import time
import tracebackfrom selenium.webdriver import ActionChains
from selenium.webdriver.common.actions.action_builder import ActionBuilder
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
import selenium.webdriver.support.expected_conditions as EC
import os
from datetime import datetimeclass Action:def __init__(self, dirver):self.driver = dirverdef find_element(self, loc):try:# WebDriverWait(self.driver, 10).until(EC.visibility_of_all_elements_located(loc))WebDriverWait(self.driver, 15).until(lambda x: x.find_element(*loc).is_displayed())element = self.driver.find_element(*loc)self.get_element_coordinate(element)except Exception as e:traceback.print_exception(e)traceback.print_stack()logging.info("页面中没有%s %" % (self.loc[1]))else:return elementdef find_elements(self, loc):try:# 保证元素可见WebDriverWait(self.driver, 15).until(EC.visibility_of_all_elements_located(loc))elements = self.driver.find_elements(*loc)except Exception as e:traceback.print_exception(e)traceback.print_stack()logging.info("页面中没有%s %" % (self.loc[1]))else:return elementsdef get_element_coordinate(self, element):rect = element.rectx, y = rect['x'], rect['y']size = element.sizewidth = size['width']height = size['height']left_up = (x, y)left_down = (x, y + height)center = (x + 0.5 * width, y + 0.5 * height)right_up = (x + width, y)right_down = (x + width, y + height)element_coordinate = dict(left_up=left_up, left_down=left_down, center=center, right_up=right_up,right_down=right_down)logging.info(element_coordinate)print(element_coordinate)return element_coordinatedef click_element(self, loc):self.find_element(loc).click()def save_element_picture(self, loc, file_name):element = self.find_element(loc)element.screenshot(file_name)def save_picture(self, filename, browser='FireFox'):file_path = os.path.dirname(os.path.dirname(__file__))now = datetime.now()picture_date_dir = now.strftime("%Y-%m-%d")formatted_date = now.strftime("%Y-%m-%d-%H-%M-%S")file_path = file_path + '\\picture\\' + picture_date_dirpicture_path = file_path + '\\' + filename + '_' + formatted_date + '.png'print(picture_path)# 检查文件路径是否存在if not os.path.exists(file_path):print('创建文件路径')# 如果文件路径不存在,创建它os.makedirs(file_path)if browser == 'FireFox':self.driver.save_full_page_screenshot(picture_path)elif browser == 'Chrome':self.driver.get_screenshot_as_file(picture_path)def save_long_picture(self, filename, browser='FireFox'):# file_path=# 截长图self.driver.save_full_page_screenshot(filename)def click_element_with_coordinate(self, x, y):action = ActionBuilder(self.driver)action.pointer_action.move_to_location(x, y).click()action.perform()def double_click(self, loc):element = self.find_element(loc)ActionChains(self.driver).double_click(element).perform()def set_high_light_elment(self, element):script = '''// 高亮显示元素arguments[0].style.backgroundColor = "yellow";// 设置红色边框arguments[0].style.border = "3px solid red";'''self.driver.execute_script(script, element)passdef browser_2_windows_coordinates_v2(self, browserX, browserY, screenWidth=1360, screenHeight=768,desktopScale=1):# location = self.get_element_location(element)# x, y = location['left_up'][0], location['left_up'][1]script = '''function getDesktopCoordinates(browserX, browserY,screenWidth,screenHeight,desktopScale) {{// 浏览器中的坐标(x, y)var browserX = browserX;var browserY = browserY;// 屏幕分辨率var screenWidth = screenWidth;var screenHeight = screenHeight;// 桌面缩放比例var desktopScale = desktopScale;//- 浏览器窗口左上角的桌面坐标为(win_x, win_y)。var win_x = window.screenX || window.screenLeft;var win_y = window.screenY || window.screenTop;//计算工具栏高度var toolbarHeight = window.outerHeight - window.innerHeight;// 计算桌面坐标var desktopX =(win_x+ browserX) * (screenWidth/window.innerWidth) ;var desktopY =(win_y+ browserY+toolbarHeight) * (screenHeight/ window.innerHeight );console.log("桌面坐标 (x, y):", desktopX, desktopY);// 创建包含坐标的对象var desktopCoordinates = {{desktopX: desktopX,desktopY: desktopY}};return desktopCoordinates;}}var coordinates = getDesktopCoordinates({browserX}, {browserY},{screenWidth},{screenHeight},{desktopScale});return coordinates;'''.format(browserX=browserX, browserY=browserY, screenWidth=screenWidth, screenHeight=screenHeight,desktopScale=desktopScale)logging.info(script)desktopCoordinates = self.driver.execute_script(script)logging.info(desktopCoordinates)return desktopCoordinatesdef mark_dom(self, x, y, color='red'):script = '''// 创建黑点DOMconst dot = document.createElement('div');dot.style.position = 'absolute';dot.style.width = '10px';dot.style.height = '10px';dot.style.backgroundColor = '{}';dot.style.borderRadius = '50%';dot.style.left = {} + 'px';dot.style.top = {} + 'px';document.body.appendChild(dot);'''.format(color, round(x, 0), round(y, 0))logging.info(script)print(script)self.driver.execute_script(script)def mark_dom_text(self, text, x, y):script = '''// 创建一个新的标记元素var newElement = document.createElement("span");// 设置标记元素的文本内容newElement.innerText = "{}";// 设置标记元素的位置样式newElement.style.position = "absolute";newElement.style.left = "{}px";newElement.style.top = "{}px";newElement.style.color = "red";// 将新的标记元素附加到目标元素中document.body.appendChild(newElement);'''.format(text, round(x, 0), round(y, 0))logging.info(script)self.driver.execute_script(script)

业务页面类BaiduHomePage

该类主要是描述待测页面中的元素及对应的操作,当页面元素发生变更时可以快速在该页面进行修改降低了业务代码和测试代码的耦合性

import timeimport pyautogui as pyautogui
from selenium.webdriver.common.by import Byfrom PythonPractise.selenium_po.page import BasePageclass BaiduHomePage(BasePage.Action):search_input_loc = (By.ID, '''kw''')search_btn_loc = (By.ID, '''su''')def search_text(self):search_input=self.find_element(self.search_input_loc)self.set_high_light_elment(search_input)location=self.get_element_coordinate(search_input)browser_x,browser_y=location['center'][0],location['center'][1]self.mark_dom(browser_x,browser_y)desktopCoordinates=self.browser_2_windows_coordinates_v2(browser_x,browser_y)x,y=desktopCoordinates['desktopX'],desktopCoordinates['desktopY']# 移动到拖拽元素中心坐标pyautogui.moveTo(x, y, duration=1, tween=pyautogui.linear)time.sleep(10)self.find_element(self.search_input_loc).send_keys('Selenium')self.click_element(self.search_btn_loc)self.save_picture('selenium')

测试类test_baidu:

测试方法类,主要描述对页面逻辑测试的验证,在此方法中会初始话待测页面类,如本例中的百度首页的测试,本类主要关注业务逻辑的操作及验证,引入页面对象降低测试代码和业务代码的耦合性增强了代码的可读性,也降低了和页面代码的耦合性。

该方法首先打开百度首页,然后搜索对应的关键字并做校验,方法结束后关闭测试会话。

import timefrom webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.chrome.service import Service as ChromeService
from selenium.webdriver.firefox.service import Service as FirefoxService
from webdriver_manager.firefox import GeckoDriverManagerfrom PythonPractise.selenium_po.page import BaiduHomePage
from selenium import webdriverclass TestCase:def setup_class(self):# self.driver = webdriver.Chrome(service=ChromeService(ChromeDriverManager().install()))# self.driver = webdriver.Chrome(executable_path='F:\\PycharmProjects\\PythonPractise\\selenium_po\\driver\\chromedriver.exe')self.driver= webdriver.Firefox(service=FirefoxService(GeckoDriverManager().install()))self.driver.get("http://www.baidu.com")def test_baidu_search(self):baidu_home_page = BaiduHomePage.BaiduHomePage(self.driver)baidu_home_page.search_text()time.sleep(5)baidu_home_page.save_picture('selenium')assert 'selenium' in self.driver.page_sourcedef teardown_class(self):self.driver.quit()

文件工具类file_util

此方法主要是定义项目的文件位置方便后面的截图文件、日志文件等其他测试过程中产生的文件的保存,大家根据实际需求进行扩展。

import os
from datetime import datetime# 获取当前日期和时间
now = datetime.now()# 格式化为 yyyy-mm-dd
formatted_date = now.strftime("%Y-%m-%d :%H:%M:%S")print(formatted_date)
project_path = os.path.dirname(os.path.dirname(__file__))
print(project_path)

运行日志:

E:\Python3.11\python.exe "E:/PyCharm Community Edition 2023.1.1/plugins/python-ce/helpers/pycharm/_jb_pytest_runner.py" --path F:\PycharmProjects\PythonPractise\selenium_po\testcase\test_baidu.py 
Testing started at 15:42 ...
Launching pytest with arguments F:\PycharmProjects\PythonPractise\selenium_po\testcase\test_baidu.py --no-header --no-summary -q in F:\PycharmProjects\PythonPractise\selenium_po\testcase============================= test session starts =============================
collecting ... collected 1 itemtest_baidu.py::TestCase::test_baidu_search ============================= 1 passed in 42.88s ==============================
PASSED                        [100%]{'left_up': (353.0, 188.3999938964844), 'left_down': (353.0, 232.3999938964844), 'center': (628.0, 210.3999938964844), 'right_up': (903.0, 188.3999938964844), 'right_down': (903.0, 232.3999938964844)}
{'left_up': (353.0, 188.3999938964844), 'left_down': (353.0, 234.3999938964844), 'center': (629.0, 211.3999938964844), 'right_up': (905.0, 188.3999938964844), 'right_down': (905.0, 234.3999938964844)}// 创建黑点DOMconst dot = document.createElement('div');dot.style.position = 'absolute';dot.style.width = '10px';dot.style.height = '10px';dot.style.backgroundColor = 'red';dot.style.borderRadius = '50%';dot.style.left = 629.0 + 'px';dot.style.top = 211.0 + 'px';document.body.appendChild(dot);{'left_up': (353.0, 188.3999938964844), 'left_down': (353.0, 234.3999938964844), 'center': (629.0, 211.3999938964844), 'right_up': (905.0, 188.3999938964844), 'right_down': (905.0, 234.3999938964844)}
{'left_up': (725.0, 15.0), 'left_down': (725.0, 55.0), 'center': (781.0, 35.0), 'right_up': (837.0, 15.0), 'right_down': (837.0, 55.0)}
F:\PycharmProjects\PythonPractise\selenium_po\picture\2023-12-02\selenium_2023-12-02-15-42-56.png
F:\PycharmProjects\PythonPractise\selenium_po\picture\2023-12-02\selenium_2023-12-02-15-43-01.png进程已结束,退出代码0

测试结果:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/191217.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【虚拟机】Docker基础 【二】

2.2.数据卷 容器是隔离环境,容器内程序的文件、配置、运行时产生的容器都在容器内部,我们要读写容器内的文件非常不方便。大家思考几个问题: 如果要升级MySQL版本,需要销毁旧容器,那么数据岂不是跟着被销毁了&#x…

微信小程序实现打分效果代码整理

一、微信小程序点击对应点击高亮 js代码 Page({data: {list: [1, 2, 3, 4, 5],active: 0},itemClickOne(e){var nume.currentTarget.dataset.value;this.setData({active:num});}, }) wxml代码 <view class"list"><view class"item {{itemactive?…

IDC MarketScape2023年分布式数据库报告:OceanBase位列“领导者”类别,产品能力突出

12 月 1 日&#xff0c;全球领先的IT市场研究和咨询公司 IDC 发布《IDC MarketScape:中国分布式关系型数据库2023年厂商评估》&#xff08;Document number:# CHC50734323&#xff09;。报告认为&#xff0c;头部厂商的优势正在扩大&#xff0c;OceanBase 位列“领导者”类别。…

C#语言高阶开发

目录 数据结构 集合 动态数组ArrayList 习题&#xff1a;声明一个Monster类&#xff0c;有一个Attack方法,用一个ArrayList去封装Monster的对象,装10个&#xff0c;遍历monster的list让他们释放攻击方法 哈希表HashTable 创建一个武器类&#xff0c;有一个属性叫做id,每个…

【数据中台】开源项目(3)-Linkis

关于 Linkis Linkis 在上层应用程序和底层引擎之间构建了一层计算中间件。通过使用Linkis 提供的REST/WebSocket/JDBC 等标准接口&#xff0c;上层应用可以方便地连接访问MySQL/Spark/Hive/Presto/Flink 等底层引擎&#xff0c;同时实现统一变量、脚本、用户定义函数和资源文件…

web:very_easy_sql(sql、ssrf、gopher协议sql注入)

题目 页面显示如下 显示不是内部用户&#xff0c;无法识别信息 查看源码&#xff0c;找到一个use.php 访问之后显示如下 随便输入了一个&#xff0c;发现url有参数显示 试一下靶机的网址&#xff0c;返回nonono 联系之前原始页面写的“不是内网用户&#xff0c;无法别识身份”…

【PTA-C语言】实验三-循环结构I

如果代码存在问题&#xff0c;麻烦大家指正 ~ ~有帮助麻烦点个赞 ~ ~ 实验三-循环结构I 7-1 求交错序列前N项和 &#xff08;分数 15&#xff09;7-2 寻找250&#xff08;分数 15&#xff09;7-3 最大公约数和最小公倍数&#xff08;分数 15&#xff09;7-4 统计字符&#xff0…

Redis 发布订阅机制深入探索

Redis 的发布订阅&#xff08;pub/sub&#xff09;机制是一种消息传递模式&#xff0c;允许消息的发送者&#xff08;发布者&#xff09;和消息的接收者&#xff08;订阅者&#xff09;通过一个中介层&#xff08;频道&#xff09;进行通信&#xff0c;而无需彼此直接交互。以下…

231202 刷题日报

周四周五&#xff0c;边值班边扯皮&#xff0c;没有刷题。。 今天主要是做了: 1. 稀疏矩阵压缩&#xff0c;十字链表法 2. 快速排序 3.349. 两个数组的交集​​​​​ 4. 174. 地下城游戏 要注意溢出问题&#xff01;

外包搞了6年,技术退步明显......

先说情况&#xff0c;大专毕业&#xff0c;18年通过校招进入湖南某软件公司&#xff0c;干了接近6年的功能测试&#xff0c;今年年初&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落!而我已经在一个企业干了四年的功能测试&#xf…

vue项目报错及解决npm run build:prod打包错误

vue项目报错及解决npm run build:prod打包错误 执行dev环境时加载失败了该变量&#xff0c;在package.json文件中 删掉 解决方法&#xff1a; 打包成功&#xff1a;

使用 OpenFunction 在任何基础设施上运行 Serverless 工作负载

作者&#xff1a; 霍秉杰&#xff1a;KubeSphere 可观测性、边缘计算和 Serverless 团队负责人&#xff0c;Fluent Operator 和 OpenFunction 项目的创始人&#xff0c;还是多个可观测性开源项目包括 Kube-Events、Notification Manager 等的作者&#xff0c;热爱云原生技术&am…

Hdoop学习笔记(HDP)-Part.16 安装HBase

目录 Part.01 关于HDP Part.02 核心组件原理 Part.03 资源规划 Part.04 基础环境配置 Part.05 Yum源配置 Part.06 安装OracleJDK Part.07 安装MySQL Part.08 部署Ambari集群 Part.09 安装OpenLDAP Part.10 创建集群 Part.11 安装Kerberos Part.12 安装HDFS Part.13 安装Ranger …

MathType 7.5.2中文版软件使用期到了怎么办?

MathType 7.5.2中文版作为一款专业的公式编辑器&#xff0c;MathType受到很多人的青睐&#xff0c;它可以将编辑好的公式保存成多种图片格式或透明图片模式&#xff0c;可以很方便的添加或移除符号、表达式等模板&#xff08;只需要简单地用鼠标拖进拖出即可)&#xff0c;也可以…

基于SpringBoot蜗牛兼职网的设计与实现

摘 要 随着科学技术的飞速发展&#xff0c;社会的方方面面、各行各业都在努力与现代的先进技术接轨&#xff0c;通过科技手段来提高自身的优势&#xff0c;蜗牛兼职网当然也不能排除在外。蜗牛兼职网是以实际运用为开发背景&#xff0c;运用软件工程原理和开发方法&#xff0c…

css中元素水平居中的方式

文章目录 前言水平居中&#xff1a;垂直居中方法一: text-align: centerdisplay: table-cell方法二:父元素静态定位子元素通过相对定位来实现方法三:通过静态和相对定位方法四 css图片居中用text-align:center无效怎么回事&#xff1f;如何让图片在DIV中水平和垂直两个方向都居…

接口自动化测试思路和实战之模块化测试脚本框架

模块化测试脚本框架 需要创建独立的可描述的模块、程序片断以及待测试应用程序的脚本。这些小脚本进行组合&#xff0c;就能组成用来独立运行特定的测试的测试用例脚本。 场景一: 开发把 access_token接口地址由/cgi-bin/token 改为/cgi-bin/get_token或者修改参数等 》开发把…

【LeetCode】链式二叉树OJ题---C语言版

链式二叉树OJ题 一、单值二叉树&#xff08;1&#xff09;题目描述&#xff1a;&#xff08;2&#xff09;思路表述&#xff1a;&#xff08;3&#xff09;代码实现&#xff1a; 二、二叉树最大深度&#xff08;1&#xff09;题目描述&#xff1a;&#xff08;2&#xff09;思路…

docker容器中创建非root用户

简介 用 docker 也有一段时间了&#xff0c;一直在 docker 容器中使用 root 用户肆意操作。直到部署 stable diffusion webui 我才发现无法使用 root 用户运行它&#xff0c;于是才幡然醒悟&#xff1a;是时候搞个非 root 用户了。 我使用的 docker 镜像文件是 centos:centos…

LeetCode的几道题

一、捡石头 292 思路就是&#xff1a; 谁面对4块石头的时候&#xff0c;谁就输&#xff08;因为每次就是1-3块石头&#xff0c;如果剩下4块石头&#xff0c;你怎么拿&#xff0c;我都能把剩下的拿走&#xff0c;所以你就要想尽办法让对面面对4块石头的倍数&#xff0c; 比如有…