PageObject三层架构模式实现

news2025/1/23 13:17:28

1:PageObject三层架构分为:

 接下来用163邮箱的登录功能来举例说明三层架构的使用。

1:先创建目录结构,如下图

 2:在工具Util中,先封装查找元素定位的工具,创建一个find_ele.py文件。内容如下:

from selenium.webdriver.support.wait import WebDriverWait


def find_element(dirver, find_type, find_express):
    '''查找元素控件'''
    try:
        element = WebDriverWait(dirver, 20).until(lambda driver:driver.find_element(find_type, find_express))
        # 20秒内,每0.5秒去查找一次元素,直到找到为止,找到就返回,如果20秒还没找到,就抛异常
        return element
    except Exception as e:
        raise e

3:接下来在pageobject三层架构中的第一层对象层,封装登录页面的元素定位及操作

在Object文件夹下创建一个loginpage.py文件,内容如下:

# 对象层
from selenium import webdriver
from Util.find_ele import find_element
from Util.read_ini import ParseConfigFile


class LoginPage:

    def __init__(self, driver):
        self.driver = driver

    def input_username(self, username):
        '''定位用户名输入控件,并输入用户名'''
        find_element(self.driver, 'name', 'email').send_keys(username)
        
    def input_password(self, password):
        '''定位密码输入控件,并输入密码'''
        find_element(self.driver, 'name', 'password').send_keys(password)
        
    def switch_frame(self):
        '''切换iframe'''
        frame = find_element(self.driver, 'tag name', 'iframe')
        self.driver.switch_to.frame(frame)

    def login_click(self):
        '''点击登录'''
        find_element(self.driver, 'id', 'dologin').click()
        

if __name__ == '__main__':
    driver = webdriver.Chrome()

    # 访问网址
    driver.get('https://mail.163.com/')

    login = LoginPage(driver)        # 初始化LoginPage类
    # 执行登录操作
    login.switch_frame()
    login.input_username('12345')
    login.input_password('123456')
    login.login_click()

4:下来是pageobject的第二层逻辑层,封装登录功能

在Module文件夹下,创建一个login.py文件,内容如下:

# 逻辑层
from Object.loginpage import LoginPage
from selenium import webdriver

class LoginModule:
    def __init__(self):
        print('------开始登录------')

    def login(self, driver, username, password):
        '''登录操作'''
        try:
            login_page = LoginPage(driver)        # 初始化对象层的LoginPage类
            login_page.switch_frame()
            login_page.input_username(username)
            login_page.input_password(password)
            login_page.login_click()
        except Exception as e:
            raise e

if __name__ == '__main__':
    driver = webdriver.Chrome()
    driver.get('https://mail.163.com/')
    login = LoginModule()
    login.login(driver, '12345', '123456')

5:pageobject第三层业务层,编写测试用例

在Scripts文件夹下创建一个以test开头的py文件,test_login.py文件内容如下:

# 业务层
from selenium import webdriver
from Moduel.login import LoginModule


def test_login():
    driver = webdriver.Chrome()
    driver.get('https://mail.163.com/')
    login = LoginModule()
    login.login(driver, '12345', '123456')

6:pageobject三层架构的核心逻辑已经写完了,但是可以发现,其中的元素定位方式和值是写死的,如果有变动,那么就要去修改对象层的每个元素的定位方式及值。

为了防止改动源文件,我们增加一个.ini文件来管理元素定位的方式及值,每次修改元素定位,就只用修改ini文件即可。

ini文件的格式为:

节[section1]
参数 name=value
参数 name=value
参数 name=value

节[section2]
参数 name=value
参数 name=value
参数 name=value

以节及它的参数来表达定位元素方式和值。section1和section2之间的参数,都是属于section1的。

登录页面的元素定位方式及值,用ini文件来表示,为:

在Setting文件夹下创建一个element_location.ini文件。

[login_page]
login_page.username = name:email
login_page.password = name:password
login_page.loginbutton = id:dologin
login_page.frame = tag name:iframe

7:ini配置文件已经完成,接下来就是要读取ini文件中的内容。

首先在Setting文件夹下,创建一个Config.py文件,用来获取文件路径。

# 获取文件地址
import os

Base_path = os.path.dirname(os.path.dirname(__file__))     # 获取根目录
print(Base_path)

# 元素定位文件
Element_Location_Path = os.path.join(Base_path, 'Setting/element_location.ini')
print(Element_Location_Path)


# 测试用例文件路径
Case_Path = os.path.join(Base_path, 'Scripts')
print(Case_Path)

然后再Util文件夹下,创建一个read_ini.py文件,来封装读取ini文件的工具类。

# 解析config.ini文件

import configparser
from Setting.Config import Element_Location_Path

class ParseConfigFile:

    def __init__(self):
        self.cf = configparser.ConfigParser()    # 初始化类
        self.cf.read(Element_Location_Path)      # 读取文件

    def getSection(self, section_name):
        '''获取section_name下的所有参数'''
        option_dict = dict(self.cf.items(section_name))
        return option_dict


if __name__ == '__main__':
    pf = ParseConfigFile()
    print(pf.getSection('login_page'))
输出:{'login_page.username': 'name:email', 'login_page.password': 'name:password', 
'login_page.loginbutton': 'id:dologin', 'login_page.frame': 'tag name:iframe'}

8:修改Object对象层中的获取元素定位的方式。

修改loginpage.py文件:

# 对象层
from selenium import webdriver
from Util.find_ele import find_element
from Util.read_ini import ParseConfigFile


class LoginPage:

    def __init__(self, driver):
        self.driver = driver
        self.pf = ParseConfigFile()
        self.option_dicts = self.pf.getSection('login_page')     # 获取定位元素的配置文件内容

    def input_username(self, username):
        '''定位用户名输入控件,并输入用户名'''
        # find_element(self.driver, 'name', 'email').send_keys(username)
        # 从读取的配置文件option_dict字典中,获取用户名输入框的定位方式及值
        location_name, location_type = self.option_dicts['login_page.username'].split(':')
        find_element(self.driver, location_name, location_type).send_keys(username)

    def input_password(self, password):
        '''定位密码输入控件,并输入密码'''
        # find_element(self.driver, 'name', 'password').send_keys(password)
        # 从读取的配置文件option_dict字典中,获取密码输入框的定位方式及值
        location_name, location_type = self.option_dicts['login_page.password'].split(':')
        find_element(self.driver, location_name, location_type).send_keys(password)

    def switch_frame(self):
        '''切换iframe'''
        # frame = find_element(self.driver, 'tag name', 'iframe')
        # 从读取的配置文件option_dict字典中,获取iframe的定位方式及值
        location_name, location_type = self.option_dicts['login_page.frame'].split(':')
        frame = find_element(self.driver, location_name, location_type)
        self.driver.switch_to.frame(frame)

    def login_click(self):
        '''点击登录'''
        # find_element(self.driver, 'id', 'dologin').click()
        # 从读取的配置文件option_dict字典中,获取登录按钮的定位方式及值
        location_name, location_type = self.option_dicts['login_page.loginbutton'].split(':')
        find_element(self.driver, location_name, location_type).click()

if __name__ == '__main__':
    driver = webdriver.Chrome()

    # 访问网址
    driver.get('https://mail.163.com/')

    login = LoginPage(driver)
    login.switch_frame()
    login.input_username('YM_yimin')
    login.input_password('yimin19960930')
    login.login_click()

9:最后,在run.py文件中,进行执行

# 执行入口
import pytest
from Setting.Config import Case_Path

if __name__ == '__main__':
    pytest.main(['-s', '-v', Case_Path])

整个PageObject三层架构框架就写完了。

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

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

相关文章

JavaScript—DOM(文档对象模型)

目录 DOM是什么? DOM有什么作用? 一、事件 理解事件 事件怎么写(要做什么就写什么)? 实战演练 1、页面加载完毕以后,打印一句话 2、如果有一个a标签,并给其添加一个点击事件 3、事件默…

电脑如何投屏到手机?Windows投屏到iPhone也可以吗?

我们知道,因为各大品牌厂商越来越维护自己的名声,都会推出“全家桶”,就是某些功能,你在使用同一品牌的电脑、手机、平板时非常好用,但一旦跨品牌就用不了。电脑投屏到手机也会遇到这种“品牌隔离”。 如果参会人使用…

对DataFrame对象中的数据将各行列进行整体平移DataFrame.shift()

【小白从小学Python、C、Java】 【计算机等级考试500强双证书】 【Python-数据分析】 对DataFrame对象中的数据 将各行列进行整体平移 DataFrame.shift() [太阳]选择题 以下python代码错误的是? import pandas as pd dfpd.DataFrame({A:[1,2,3],B:[4,5,6]}) print(【显示】df&…

SAP MM学习笔记26- SAP中 振替转记(转移过账)和 在库转送(库存转储)3- Plant间在库转送

SAP 中在库移动 不仅有入库(GR),出库(GI),也可以是单纯内部的转记或转送。 1,振替转记(转移过账) 2,在库转送(库存转储) 1&#xff…

springboot+vue健身房俱乐部课程预约网站的设计与实现0356t

通过对知识内容的学习研究,进而设计并实现一个“力炫”健身馆网站。系统能实现的主要功能应包括;用户、健身教练、健身器材、健身课程、健身商品、健身资讯等的一些操作,传统的管理模式主要是使用纸作为介质,信息交流很大程度上受…

ASL芯片CS5366带DSC影像解压 替代PS186替代RTD2173替代AG9411 集睿致远方案设计优势

CS5366是ASL集睿致远推出的2LAN带PD(最高100W)可拉U3口的高集成度芯片,分辨率支持4K60HZ。在刷新率上,CS5366作为升级一代,超越了CS5266达到60HZ,同时在各个方面做到了优越性,极具性价比的一代&…

如何使用CSS实现一个自适应等高布局?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 使用 Flexbox 布局⭐ 使用 Grid 布局⭐ 写在最后 ⭐ 专栏简介 前端入门之旅:探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅 欢迎来到前端入门之旅!这个专栏是为那些对Web开发…

海康VisionMaster-全局变量-全局脚本-全局通讯

using System; using VM.GlobalScript.Methods; using System.Windows.Forms; using iMVS_6000PlatformSDKCS; using System.Runtime.InteropServices;/******************************* 示例说明: 接收全局通信模块数据示例* 前提: 全局通信模块中开启有通信设备* 控制逻…

Mycat单库分表

Mycat单库分表 一、准备工作 1.MySQL主从同步、JDK。 2.mycat解压即可,无需安装。 3.如果用的是云服务器,需要开放8066端口。 二、配置文件 1.server.xml:定义用户以及系统相关变量,如端口(默认8066&#xff0…

【golang】15、cobra cli 命令行库

Cobra 是 golang 最流行的命令行库,文档见 一、脚手架 mkdir pt && cd pt && go mod init cobra-cli init # 在项目下运行即可生成脚手架# tree . ├── LICENSE ├── cmd # 生成了cmd目录 │ └── root.go # 生成了root.go, 其中定义了ro…

Kubernetes(k8s)上部署redis5.0.14

Kubernetes上部署redis 环境准备创建命名空间 准备PV和PVC安装nfs准备PV准备PVC 部署redis创建redis的配置文件部署脚本挂载数据目录挂载配置文件通过指定的配置文件启动redis 集群内部访问外部链接Redis 环境准备 首先你需要一个Kubernetes环境,可参考我写的文章&…

LLM - Baichuan-13B 多卡加载与推理测试

目录 ​编辑 一.引言 二.模型加载 1.量化加载 ◆ 基础配置 ◆ 8_bit 加载 ◆ 4_bit 加载 2.多卡加载 ◆ API 加载 ◆ accelerate 加载 三.模型推理 1.显存查看 ◆ Nvidia 显卡监控 ◆ Python subprocess 调用 2.双卡推理 ◆ 双卡 divice 分配 ◆ 双卡推理 GPU…

Redis数据结构:Zset类型全面解析

Redis,作为一种高性能的键值对数据库,因其丰富的数据类型和高效的性能而受到了广泛的关注和使用。在 Redis 的五种主要数据类型中,Zset(有序集合)类型可能是最复杂,但也是最强大的一种。Zset 不仅可以存储键…

【JavaSE专栏90】用最简单的方法,使用 JDBC 连接 MySQL 数据库

作者主页:Designer 小郑 作者简介:3年JAVA全栈开发经验,专注JAVA技术、系统定制、远程指导,致力于企业数字化转型,CSDN学院、蓝桥云课认证讲师。 主打方向:Vue、SpringBoot、微信小程序 本文讲解了如何使用…

git-tf clone 路径有空格处理方案

git-tf clone 路径存在空格情况下,运行命令报错; 需要对路径进行双引号处理

汽车电子笔记之:基于AUTOSAR的电机控制器架构设计

目录 1、概述 2、AUTOSAR设计 2.1、SWC设计 2.2、PORT设计 2.3、Runnable设计 2.4、电机控制器OS实现 1、概述 电机控制器应用层的软件架构较为复杂,主要包括PMSM(Permanent-MagnetSynchronous Motor)的矢量控制算法。根据PMSM的控制算法,对算法中的软件功能进行分析&…

Linux 多线程同步机制(上)

文章目录 前言一、线程同步二、互斥量 mutex三、死锁总结 前言 一、线程同步 在多线程环境下,多个线程可以并发地执行,访问共享资源(如内存变量、文件、网络连接 等)。 这可能导致 数据不一致性, 死锁, 竞争条件等 问题。 为了解…

【LeetCode-中等题】138. 复制带随机指针的链表

文章目录 题目解题核心思路:找random指针指向思路一:哈希思路二:迭代构造新链表 方法一:哈希递归方法二:纯哈希方法三:迭代 节点拆分 题目 解题核心思路:找random指针指向 这里的拷贝属于深拷…

Leetcode刷题:395. 至少有 K 个重复字符的最长子串、823. 带因子的二叉树

Leetcode刷题:395. 至少有 K 个重复字符的最长子串、823. 带因子的二叉树 1. 395. 至少有 K 个重复字符的最长子串算法思路参考代码和运行结果 2. 823. 带因子的二叉树算法思路参考代码和运行结果 1. 395. 至少有 K 个重复字符的最长子串 题目难度:中等 标签&#…

lenovo联想笔记本小新Air-15 2021款Intel版ITL版(82GM)原装出厂Win10系统

自带所有驱动、出厂主题壁纸LOGO、Office办公软件、联想电脑管家等预装程序 所需要工具:16G或以上的U盘 文件格式:ISO 文件大小:11.2GB 链接:https://pan.baidu.com/s/12NTMOt5eUjOIsbayXPyiww?pwdrs4v 提取码&#xf…