PageObject三层架构模式实现之数据驱动

news2024/11/29 0:48:09

接上一篇PageObject三层架构模式实现,发现我们的用户名和密码都是在代码中写死的,如果要测试不同用户名和密码的登录,那么每执行一次就要修改一次代码。这样效果非常不好。

因此本篇文章介绍如何实现数据驱动并且记录下每次操作的日志。

在上一篇文章的基础下,我们再增加两个文件夹,一个TestData文件夹用来存放测试数据,一个Logs文件夹用来存放执行过程中记录的日志信息。

1:先来简单看一下目录结构:

整体目录结果不变,增加了两个文件夹

2:我们把需要用到的参数都放到excel文件中,再将excel文件放到TestData文件夹下,excel文件的内容如下(仅参考):

接下来,就是把excel文件中的内容读取出来。

在Util文件夹下,创建一个excel_parse.py文件,用来读取excel中的内容,具体内容如下:

from openpyxl import load_workbook
from Setting.Config import Test_Data_Path


class ExcelParse:

    def __init__(self):
        self.workbook = None
        self.sheet = None

    def load_workbook(self, filename):
        '''加载文件'''
        try:
            self.workbook = load_workbook(filename)
        except Exception as e:
            raise e

    def get_sheet_by_name(self, sheetname):
        '''根据sheetname加载某一页'''
        try:
            self.sheet = self.workbook[sheetname]
        except Exception as e:
            raise e

    def get_row_num(self):
        '''返回行数'''
        return self.sheet.max_row

    def get_col_num(self):
        '''返回列数'''
        return self.sheet.max_column

    def get_cell_value(self, row, col):
        '''获取某一单元格的值'''
        try:
            cell_value = self.sheet.cell(row=row, column=col).value
            return cell_value
        except Exception as e:
            raise e

    def get_row_value(self, row):
        '''返回某一行的值'''
        try:
            cols = self.get_col_num()
            row_value = []
            for i in range(1, cols+1):
                # row_value.append(self.sheet.cell(row=row, column=i).value)
                row_value.append(self.get_cell_value(row, i))
            return row_value
        except Exception as e:
            raise e


if __name__ == '__main__':
    excel = ExcelParse()
    excel.load_workbook(Test_Data_Path)
    excel.get_sheet_by_name('login')
    res = excel.get_row_value(2)
    print(res)

3:接下来就可以修改pageobject三层架构的第三层,业务层test_login.py文件的内容,修改内容如下:

from Module.login import Login
from Util.excel_parse import ExcelParse
from Setting.Config import Test_Data_Path
from selenium import webdriver


def test_login():
    try:
        # 获取数据
        excel = ExcelParse()
        excel.load_workbook(Test_Data_Path)
        excel.get_sheet_by_name('login')

        rows = excel.get_row_num()
        row1_value = excel.get_row_value(1)
        # 遍历每一行数据
        for i in range(2, rows+1):
            tmp_row_value = excel.get_row_value(i)
            # 将表头与数据聚合成一个字典,方便调用
            tmp_dict = dict(zip(row1_value, tmp_row_value))
            print(tmp_dict)
            username = tmp_dict['用户名']
            password = tmp_dict['密码']

            driver = webdriver.Chrome()
            driver.get('https://mail.163.com/')
            login = Login()
            login.login(driver, username, password)

    except Exception as e:
        raise e

如此就实现了参数化,想传什么参数,直接修改excel文件即可。

4:最后是记录日志,记录日志用的是第三方库:loguru模块

首先先安装loguru模块(pip install loguru)

接下来创建一个Logs文件夹,用来存放日志文件。

在Util文件夹下创建一个日志工具类log_util.py文件,具体内容如下:

from loguru import logger
from Setting.Config import Log_Path


class Log:

    def __new__(cls, *args, **kwargs):
        if not hasattr(cls, 'instance'):
            cls.instance = super(Log, cls).__new__(cls)
        return cls.instance

    def __init__(self):
        logger.add(Log_Path + '/runtime_{time}.log')       # 日志存放位置及日志名称

    def debug(self, message):
        logger.debug(message)

    def info(self, message):
        logger.info(message)

    def warning(self, message):
        logger.warning(message)

    def error(self, message):
        logger.error(message)

log = Log()

5:在pageobject的对象层(loginpage.py文件),导入log,并对操作进行记录,如下:

# 对象层
from selenium import webdriver
from Util.find_ele import find_element
from Util.read_ini import ParseConfigFile
from Util.log_util import log
 
 
class LoginPage:
 
    def __init__(self, driver):
        self.driver = driver
 
    def input_username(self, username):
        '''定位用户名输入控件,并输入用户名'''
        log.info('定位用户名输入框,并输入用户名')
        find_element(self.driver, 'name', 'email').send_keys(username)
        
    def input_password(self, password):
        '''定位密码输入控件,并输入密码'''
        log.info('定位密码输入框,并输入密码')
        find_element(self.driver, 'name', 'password').send_keys(password)
        
    def switch_frame(self):
        '''切换iframe'''
        log.info('切换iframe')
        frame = find_element(self.driver, 'tag name', 'iframe')
        self.driver.switch_to.frame(frame)
 
    def login_click(self):
        '''点击登录'''
        log.info('定位登录按钮,并点击登录')
        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()

如此,一个简单的pageobject框架就完成。其中呢还有一些可以优化的地方,这里就不再进行优化了,可以根据自己的想法对代码进行优化,这只是给自己刚学习使用pageobject三层架构的一个记录。

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

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

相关文章

SpringBoot - Google EventBus、AsyncEventBus

介绍 EventBus 顾名思义,事件总线,是一个轻量级的发布/订阅模式的应用模式,最初设计及应用源与 google guava 库。 相比于各种 MQ 中间件更加简洁、轻量,它可以在单体非分布式的小型应用模块内部使用(即同一个JVM范围…

数字孪生智慧工厂:电缆厂 3D 可视化管控系统

近年来,我国各类器材制造业已经开始向数字化生产转型,使得生产流程变得更加精准高效。通过应用智能设备、物联网和大数据分析等技术,企业可以更好地监控生产线上的运行和质量情况,及时发现和解决问题,从而提高生产效率…

Vlan和Trunk

文章目录 一、VLAN的定义与背景1. 传统以太网的问题(广播域)2. 用VLAN隔离广播域3. VLAN的优点与应用 二、VLAN的转发过程举例三、802.1Q标签:帧格式与作用四、VLAN工作原理交换机端口类型AccessTrunkHybrid PVID(Port VLAN ID&am…

十三、享元模式

一、什么是享元模式 享元(Flyweight)模式的定义:运用共享技术来有效地支持大量细粒度对象的复用。它通过共享已经存在的对象来大幅度减少需要创建的对象数量、避免大量相似类的开销,从而提高系统资源的利用率。 享元(F…

C语言拷贝一个文件。

今天学习了如何用c语言拷贝一个文件&#xff0c;一个字符一个字符的拷贝一个文件&#xff0c;特此记录一下。 #include<stdio.h>int main() {FILE * pfr fopen("1.txt", "r"); //打开文件1.txt 用读的模式if (pfr NULL){return 1;}FILE* pfw fo…

1.RTKLIB环境配置和调试

1.源码下载 下载链接&#xff1a;rtklib 注&#xff1a;2.4.2 p13为稳定版本&#xff08;标识p代表稳定版本&#xff09;&#xff0c;2.4.3 b34为最新实验版本&#xff08;标识b&#xff09;。点击2.4.3 b34 的Source Programs and Data 链接下载源码。 2.环境配置 **集成…

Linux系统文件权限修改:permission denied

最近遇到文件夹权限的问题 通过命令发现www缺少写和执行的权限 然后赋予所有权限 下面是一些详解&#xff1a; 要赋予文件或目录写入权限&#xff0c;可以使用 chmod 命令。 命令的基本语法是&#xff1a; chmod <permissions> <file or directory>其中 <…

【测试】笔试01

文章目录 1. 按照瀑布模型的阶段划分&#xff0c;软件测试可以分为单元测试&#xff0c;集成测试&#xff0c;系统测试。请问以下哪项测试不属于系统测试的内容&#xff08; &#xff09;2. 测试设计员的职责有哪些&#xff1f;3. 针对程序段&#xff1a;IF&#xff08;A||B||C…

xsschallenge靶场练习1-13关

文章目录 第一关第二关第三关第四关第五关第六关第七关第八关第九关第十关第十一关第十二关第十三关 第一关 观察页面 http://192.168.80.139/xsschallenge/level1.php?nametest尝试在name后面输入最近基本的xss语法 <script>alert(1)</script>第二关 查看页面源…

Java【手撕滑动窗口】LeetCode 3. “无重复字符的最长子串“, 图文详解思路分析 + 代码

文章目录 前言一、长度最小子数组1, 题目2, 思路分析3, 代码 前言 各位读者好, 我是小陈, 这是我的个人主页, 希望我的专栏能够帮助到你: &#x1f4d5; JavaSE基础: 基础语法, 类和对象, 封装继承多态, 接口, 综合小练习图书管理系统等 &#x1f4d7; Java数据结构: 顺序表, 链…

(二十)大数据实战——Flume数据采集的基本案例实战

前言 本节内容我们主要介绍几个Flume数据采集的基本案例&#xff0c;包括监控端口数据、实时监控单个追加文件、实时监控目录下多个新文件、实时监控目录下的多个追加文件等案例。完成flume数据监控的基本使用。 正文 监控端口数据 ①需求说明 - 使用 Flume 监听一个端口&am…

Unity碰撞检测

Unity碰撞检测 前言准备材料代码使用OnCollisionEnter()进行碰撞Collider状态代码 使用OnTriggerEnter()进行碰撞Collider状态代码 区别代码OnCollisionEnter()OnTriggerEnter() 碰撞显示效果OnCollisionEnter()OnTriggerEnter() 提示结语 前言 碰撞检测可以说时学习Unity中最…

时间复杂度和空间复杂度的最小单位是什么

C数据结构与算法 目录 时间复杂度&#xff1a;CPU读写一次内存算作时间复杂度的最小单位。 读内存的场景&#xff1a;获取变量的值。 例如&#xff1a; if(x < 1000) 写内存的场景&#xff1a;给变量赋值。 例如&#xff1a;x 1000 空间复杂度&#xff1a;内存占用一…

VueX 与Pinia 一篇搞懂

VueX 简介 Vue官方&#xff1a;状态管理工具 状态管理是什么 需要在多个组件中共享的状态、且是响应式的、一个变&#xff0c;全都改变。 例如一些全局要用的的状态信息&#xff1a;用户登录状态、用户名称、地理位置信息、购物车中商品、等等 这时候我们就需要这么一个工…

启莱OA treelist.aspx SQL注入

子曰&#xff1a;“为政以德&#xff0c;譬如北辰&#xff0c;居其所&#xff0c;而众星共之。” 漏洞复现 访问漏洞url&#xff1a; 使用SQLmap对参数 user 进行注入 漏洞证明&#xff1a; 文笔生疏&#xff0c;措辞浅薄&#xff0c;望各位大佬不吝赐教&#xff0c;万分感…

Java“牵手”1688淘口令转换API接口数据,1688API接口申请指南

1688平台商品淘口令接口是开放平台提供的一种API接口&#xff0c;通过调用API接口&#xff0c;开发者可以获取1688商品的标题、价格、库存、商品快递费用&#xff0c;宝贝ID&#xff0c;发货地&#xff0c;区域ID&#xff0c;快递费用&#xff0c;月销量、总销量、库存、详情描…

juicefs源码format命令阅读

之前博文中介绍过在windows下安装GO和vscode windows下安装go环境 和vscode中go扩展调试 1、获取源码 git clone https://github.com/juicedata/juicefs.git 首先观察代码架构 上图是我已经编译过得代码&#xff0c;可能和刚git下来的有些出入。 2、编译 我是在windows上进…

C++学习笔记总结练习:运算符重载两种方式

运算符重载的两种方式 1 基本概念 基础 运算符时具有特殊名字的函数&#xff1a;由关键字operator和气候定义的运算符共同组成。 可以被重载的运算符 方式 将运算符重载为类的成员函数。重载运算符函数&#xff0c;并声明为类的友元。 规则 重载后的运算符必须至少有一个…

可控硅调功电路原理

在常见的马达调速以及需要调整负载功率的场合&#xff0c;经常会用到可控硅调功电路&#xff0c;下图是常见的应用电路。 调功电路主要由阻容移相电路和可控硅触发电路构成&#xff0c;工作过程如下&#xff0c;当交流电的正半周时&#xff0c;交流电通过R5,可调电阻R3给电容C1…

Elasticsearch数据库操作

索引操作 新建索引 PUT /ztt {"mappings": {"properties": {"info":{"type": "text","analyzer": "ik_smart"},"email":{"type": "keyword","index": false…