关于Selenium的网页对象单元测试的设计模式
写在前面:经过了实践总结一下经验,心得进行一个分享。
首先driver是可以单独抽出来的,变成一个driver函数放在driver.py。
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Optionsdef get_chrome_driver():# 启动driveroptions = Options()# 替换为你本地的Chromed路径options.binary_location = r"D:\software\Chrome-bin\chrome.exe"# 替换为你本地的Chromedriver路径chromedriver_path = r'D:\software\Chrome-bin\chromedriver.exe'# 使用Service对象指定Chromedriver路径service = Service(chromedriver_path)driver = webdriver.Chrome(service=service, options=options)return driver
然后我们新建page.py,在这里我们只处理页面的对象,因此我们创建页面类在此,当然这个页面类需要和HTML元素和驱动进行组合才能形成一个页面。
我们创建BasePage,以后的页面类都用它作为基类。首先是传一个驱动,组合起来
class BasePage(object):"""Base class to initialize the base page that will be called from allpages"""def __init__(self, driver):self.driver = driverclass LoginPage(BasePage):def __init__(self, driver):super().__init__(driver)
接着我们在element.py创建元素的基类,以后的元素类都继承自它
from selenium.webdriver.support.ui import WebDriverWaitclass BaseElement(object):"""Base page class that is initialized on every page object class."""locator = Nonedef __set__(self, obj, value):"""Sets the text to the value supplied"""driver = obj.driverWebDriverWait(driver, 5).until(lambda dri: dri.find_element(*self.locator))driver.find_element(*self.locator).clear()driver.find_element(*self.locator).send_keys(value)def __get__(self, obj, owner):"""Gets the specified element object"""driver = obj.driverWebDriverWait(driver, 5).until(lambda dri: dri.find_element(*self.locator))self.element = driver.find_element(*self.locator)return self.elementdef click(self):self.element.click()def get_text(self):return self.element.get_attribute("value")
接着我们在locator.py创建定位器类,没什么特别,就是作为一个类似字典的静态类存放元素的位置
from selenium.webdriver.common.by import Byclass LonginPageLocators(object):"""A class for login page locators. All login page locators should come here"""basic_username = (By.ID, 'basic_username')basic_password = (By.ID, 'basic_password')details_button = (By.ID, 'details-button')proceed_link = (By.ID, 'proceed-link')login_button = (By.ID, 'submitBtn')
准备工作就绪,那么我们来编写LoginPage吧~
首先组合我们需要的HTML元素,然后编写一个login业务函数进行业务处理。
class BasePage(object):"""Base class to initialize the base page that will be called from allpages"""def __init__(self, driver):self.driver = driverclass LoginPage(BasePage):def __init__(self, driver):super().__init__(driver)class DetailButtonElement(BaseElement):locator = LonginPageLocators.details_buttonclass ProceedLinkElement(BaseElement):locator = LonginPageLocators.proceed_linkclass UsernameTextElement(BaseElement):locator = LonginPageLocators.basic_usernameclass PasswordTextElement(BaseElement):locator = LonginPageLocators.basic_passwordclass LoginButtonElement(BaseElement):locator = LonginPageLocators.login_buttonclass RankBoxElement(BaseElement):locator = LonginPageLocators.rank_boxdetail_button_ele = DetailButtonElement()proceed_link_ele = ProceedLinkElement()username_text_ele = UsernameTextElement()password_text_ele = PasswordTextElement()login_button_ele = LoginButtonElement()rank_box_ele = RankBoxElement()def login(self):self.detail_button_ele.click()self.proceed_link_ele.click()self.username_text_ele = 'admin'self.password_text_ele = '123456'self.login_button_ele.click()_ = self.rank_box_ele # just test web is complete
_ = self.rank_box_ele小细节是用来测试是否进入主页面的。
回到单元测试.py添加测试函数,debug运行。
def test_login(self):login_page = page.LoginPage(self.driver)login_page.login()
当我们登录成功后,我们就可以跳转到我们需要页面,进行脚本处理。当然了进入了新的页面,别忘了创建新的页面类。在我的例子中就是创建了新的页面类ResourceDetailPage以便完成后续的业务。
def test_turn_to_resource(self):self.test_login()# 页面跳转self.driver.get("https://127.0.0.1:38000/#/resource/detail/3668")def test_resource_delete(self):self.test_turn_to_resource()# 创建新的page对象resource_detail_page = page.ResourceDetailPage(self.driver)# 在新的page处理业务...resource_detail_page.while_delete()
相关文章:
关于Selenium的网页对象单元测试的设计模式
写在前面:经过了实践总结一下经验,心得进行一个分享。 首先driver是可以单独抽出来的,变成一个driver函数放在driver.py。 from selenium import webdriver from selenium.webdriver.chrome.service import Service from selenium.webdriver…...
基于多反应堆的高并发服务器【C/C++/Reactor】(上)
(一)初始化服务器端用于监听的套接字 Server.h #pragma once // 初始化监听的套接字 int initListenFd(unsigned short port); Server.c int initListenFd(unsigned short port) {// 1.创建监听的fdint lfd socket(AF_INET, SOCK_STREAM, 0);if(lf…...
腾讯云debian服务器的连接与初始化
目录 1. 远程连接2. 软件下载3. 设置开机自启动 1. 远程连接 腾讯云给的服务器在安装好系统之后,只需要在防火墙里面添加一个白名单(ip 或者域名)就能访问了。 浏览器打开https://www.ipip.net/,在左下角找到自己所用的WIFI的公…...
医保购药小程序:智能合约引领医疗数字革新
在医疗领域,医保购药小程序通过引入智能合约技术,为用户提供更为高效、安全的购药体验。本文将通过简单的智能合约代码示例,深入探讨医保购药小程序如何利用区块链技术中的智能合约,实现医保结算、购药监控等功能,为医…...
神经网络:深度学习优化方法
1.有哪些方法能提升CNN模型的泛化能力 采集更多数据:数据决定算法的上限。 优化数据分布:数据类别均衡。 选用合适的目标函数。 设计合适的网络结构。 数据增强。 权值正则化。 使用合适的优化器等。 2.BN层面试高频问题大汇总 BN层解决了什么问…...
Unity中Shader旋转矩阵(二维旋转矩阵)
文章目录 前言一、旋转矩阵的原理1、我们以原点为中心,旋转坐标轴θ度2、求 P~2x~:3、求P~2y~:4、最后得到 P~2~点 的点阵5、该点阵可以拆分为以下两个矩阵相乘的结果 二、在Shader中,使用该旋转矩阵实现围绕 z 轴旋转1、在属性面板定义 floa…...
前端面试题(计算机网络):options请求方法及使用场景
OPTIONS请求方法及使用场景 回答思路:什么是options请求-->options请求方法-->options使用场景什么是options请求?(浅入)扩展:常见的HTTP请求有什么?扩展:常见的HTTP请求的作用࿱…...
使用docker-compose管理docker服务
使用docker-compose管理docker服务 1,创建docker-compose.yml version: 3 services:javaapp:build: context: ./javaappdockerfile: Dockerfileports:- "9202:9202"- "19202:19202"goapp:build: context: ./goappdockerfile: Dockerfileports…...
Python_Tkinter和OpenCV模拟行星凌日传输光度测定
传输光度测定 在天文学中,当相对较小的天体直接经过较大天体的圆盘和观察者之间时,就会发生凌日。 当小物体移过较大物体的表面时,较大物体会稍微变暗。 最著名的凌日是水星和金星对太阳的凌日。 借助当今的技术,天文学家可以在…...
【安全】使用auparse解析auditd审计日志
使用auparse解析auditd审计日志 1 审计日志特点 查看auditd.log的日志,审计日志的格式如下: typeSYSCALL msgaudit(1703148319.954:11680975): archc000003e syscall2 successyes exit5 a01102430 a10 a21b6 a324 items1 ppid7752 pid7761 auid0 uid0…...
flink watermark 实例分析
WATERMARK 定义了表的事件时间属性,其形式为: WATERMARK FOR rowtime_column_name AS watermark_strategy_expression rowtime_column_name 把一个现有的列定义为一个为表标记事件时间的属性。该列的类型必须为 TIMESTAMP(3)/TIMESTAMP_LTZ(3),且是 sche…...
系列十二(面试)、Java中的GC回收类型有哪些?
一、Java中的GC回收类型 1.1、概述 Java中的GC回收类型主要包含以下几种,即:UseSerialGC、UseParallelGC、UseConcMarkSweepGC、UseParNewGC、UseParallelOldGC、UseG1GC。 1.2、源码...
华为数通方向HCIP-DataCom H12-831题库(多选题:201-220)
第201题 在多集群RR组网中,每个集群中部署了一台RR设备及其客户机,各集群的RR与为非客户机关系,并建立IBGP全连接。以下关于BGP路由反射器发布路由规则的描述,正确的有哪些? A、若某RR从EBGP对等体学到的路由,此RR会传递给其他集群的RR B、若某RR从非客户机IBGP对等体学…...
NLP论文阅读记录 - | 使用GPT对大型文档集合进行抽象总结
文章目录 前言0、论文摘要一、Introduction二.相关工作2.1Summarization2.2 神经网络抽象概括2.2.1训练和测试数据集。2.2.2 评估。 2.3 最先进的抽象摘要器 三.本文方法3.1 查询支持3.2 文档聚类3.3主题句提取3.4 语义分块3.5 GPT 零样本总结 四 实验效果4.1数据集4.2 对比模型…...
华为全屋wifi6蜂鸟套装标准
华为政企42 华为政企 目录 上一篇华为安防监控摄像头下一篇华为企业级无线路由器...
系列二十八、如何在Oracle官网下载JDK的api文档
一、官网下载JDK的api文档 1.1、官网地址 https://www.oracle.com/java/technologies/javase-jdk21-doc-downloads.html 1.2、我分享的api.chm 链接:https://pan.baidu.com/s/1Bf55Fz-eMTErmQDtZZcewQ?pwdyyds 提取码:yyds 1.3、参考 https://ww…...
STM32-ADC模数转换器
目录 一、ADC简介 二、逐次逼近型ADC内部结构 三、STM32内部ADC转换结构 四、ADC基本结构 五、输入通道 六、转换模式 6.1单次转换,非扫描模式 6.2连续转换,非扫描模式 6.3单次转换,扫描模式 6.4连续转换,扫描模式 七、…...
谷歌手机安装证书到根目录
1、前提你已经root,安装好面具 2,下载movecert模块,自动帮你把证书从用户证书移动成系统证书 视频教程,手机为谷歌手机 https://www.bilibili.com/video/BV1pG4y1A7Cj?p11&vd_source9c0a32b00d6d59fecae05b4133f22f06 软件下…...
代码随想录 322. 零钱兑换
题目 给你一个整数数组 coins ,表示不同面额的硬币;以及一个整数 amount ,表示总金额。 计算并返回可以凑成总金额所需的 最少的硬币个数 。如果没有任何一种硬币组合能组成总金额,返回 -1 。 你可以认为每种硬币的数量是无限的。…...
【图的应用二:最短路径】- 用 C 语言实现迪杰斯特拉算法和弗洛伊德算法
目录 一、最短路径 二、迪杰斯特拉算法 三、弗洛伊德算法 一、最短路径 假若要在计算机上建立一个交通咨询系统,则可以采用图的结构来表示实际的交通网络。如下图所示,图中顶点表示城市,边表示城市间的交通联系。 这个咨询系统可以回答旅…...
SkyWalking 10.2.0 SWCK 配置过程
SkyWalking 10.2.0 & SWCK 配置过程 skywalking oap-server & ui 使用Docker安装在K8S集群以外,K8S集群中的微服务使用initContainer按命名空间将skywalking-java-agent注入到业务容器中。 SWCK有整套的解决方案,全安装在K8S群集中。 具体可参…...
边缘计算医疗风险自查APP开发方案
核心目标:在便携设备(智能手表/家用检测仪)部署轻量化疾病预测模型,实现低延迟、隐私安全的实时健康风险评估。 一、技术架构设计 #mermaid-svg-iuNaeeLK2YoFKfao {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg…...
iPhone密码忘记了办?iPhoneUnlocker,iPhone解锁工具Aiseesoft iPhone Unlocker 高级注册版分享
平时用 iPhone 的时候,难免会碰到解锁的麻烦事。比如密码忘了、人脸识别 / 指纹识别突然不灵,或者买了二手 iPhone 却被原来的 iCloud 账号锁住,这时候就需要靠谱的解锁工具来帮忙了。Aiseesoft iPhone Unlocker 就是专门解决这些问题的软件&…...
【C语言练习】080. 使用C语言实现简单的数据库操作
080. 使用C语言实现简单的数据库操作 080. 使用C语言实现简单的数据库操作使用原生APIODBC接口第三方库ORM框架文件模拟1. 安装SQLite2. 示例代码:使用SQLite创建数据库、表和插入数据3. 编译和运行4. 示例运行输出:5. 注意事项6. 总结080. 使用C语言实现简单的数据库操作 在…...
C++八股 —— 单例模式
文章目录 1. 基本概念2. 设计要点3. 实现方式4. 详解懒汉模式 1. 基本概念 线程安全(Thread Safety) 线程安全是指在多线程环境下,某个函数、类或代码片段能够被多个线程同时调用时,仍能保证数据的一致性和逻辑的正确性…...
项目部署到Linux上时遇到的错误(Redis,MySQL,无法正确连接,地址占用问题)
Redis无法正确连接 在运行jar包时出现了这样的错误 查询得知问题核心在于Redis连接失败,具体原因是客户端发送了密码认证请求,但Redis服务器未设置密码 1.为Redis设置密码(匹配客户端配置) 步骤: 1).修…...
管理学院权限管理系统开发总结
文章目录 🎓 管理学院权限管理系统开发总结 - 现代化Web应用实践之路📝 项目概述🏗️ 技术架构设计后端技术栈前端技术栈 💡 核心功能特性1. 用户管理模块2. 权限管理系统3. 统计报表功能4. 用户体验优化 🗄️ 数据库设…...
SiFli 52把Imagie图片,Font字体资源放在指定位置,编译成指定img.bin和font.bin的问题
分区配置 (ptab.json) img 属性介绍: img 属性指定分区存放的 image 名称,指定的 image 名称必须是当前工程生成的 binary 。 如果 binary 有多个文件,则以 proj_name:binary_name 格式指定文件名, proj_name 为工程 名&…...
PAN/FPN
import torch import torch.nn as nn import torch.nn.functional as F import mathclass LowResQueryHighResKVAttention(nn.Module):"""方案 1: 低分辨率特征 (Query) 查询高分辨率特征 (Key, Value).输出分辨率与低分辨率输入相同。"""def __…...
Go 并发编程基础:通道(Channel)的使用
在 Go 中,Channel 是 Goroutine 之间通信的核心机制。它提供了一个线程安全的通信方式,用于在多个 Goroutine 之间传递数据,从而实现高效的并发编程。 本章将介绍 Channel 的基本概念、用法、缓冲、关闭机制以及 select 的使用。 一、Channel…...
