Python-基于数据驱动模式的自动化测试框架搭建的的逐步实现(二)

2023-11-19

Python-基于数据驱动模式的自动化测试框架搭建的的逐步实现(二)

                                                              ------封装走起!!

后续关于 <Python-基于数据驱动模式的自动化测试框架搭建的的逐步实现> 的博客例子全部基于:126邮箱登录并新建联系人,这个例子来实现的;


大家好,我们继续 <Python-基于数据驱动模式的自动化测试框架搭建的的逐步实现> 之旅,本篇博客开始我们要进入封装的旅途。

首先我们建一个工程,这里面我用的IDE是pycharm,个人觉得还是比较好用的;

这里给初学语言的小朋友们一点小建议:

开始练习编写的时候不建议使用IDE,因为大部分IDE具备联想功能,这样不利于记忆常用命令。我最开始的时候就用的写字板,着实好用,除了空格要手动敲,没有颜色以外,真心不错,可以强化记忆。

这里我给本次工程取的名字叫:data_driven_framework

在本篇博客中,我们要先封装5个packages出来:Until、Conf、PageObject、ProjectVar、TestData

1、Util(相当于底层工具,复用次数多)U

Util中包括一下文件:读写Excel的方法、获取页面元素的方法、读取配置文件的方法、获得driver的方法、

1.1 获取页面元素的封装【driver.find_element_by(LocateType,LocateExpression)】-----ObjectMap.py


从Python-基于数据驱动模式的自动化测试框架搭建的的逐步实现(一)中我们可以看到,好多代码是重复编写的,比如:driver.find_element_by(LocateType,LocateExpression),那么就可以把这个获取元素的操作封装起来,后面要对元素进行操作的时候,直接调用获取元素的方法就好了,这样就降低了代码的冗余度;

话不多说,上代码:

#encoding=utf-8
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support.ui import Select
import time

def getEelement(driver,locateType,locateExpression):
    #获取页面单个元素
    try:
        wait=WebDriverWait(driver,10)
        return wait.until(lambda x:x.find_element(locateType,locateExpression))
    except Exception,e:
        raise e

def getElements(driver,locateType,locateExpression):
    #获取页面多个元素
    try:
        wait=WebDriverWait(driver,10)
        return wait.until(lambda x:x.find_elements(locateType,locateExpression))
    except Exception,e:
        raise e

#对于下拉框标签是select的元素的获取特有操作
def getSelectElementWithIndex(driver,index_num):
    #获取select下拉框元素---index
    select_element=Select(driver.find_element_by_xpath('//select'))
    #打印已选中的文本
  print select_element.all_selected_options[0].text
    return select_element.select_by_index(index_num)

def getSelectElementWithText(driver,text):
    #获取select下拉框元素----text
    select_element=Select(driver.find_element_by_xpath('//select'))
    #打印已选中的文本
  print select_element.all_selected_options[0].text
    return select_element.select_by_visible_text(text)

def getSelectElementWithValue(driver,value):
    #获取select下拉框元素---value
    select_element=Select(driver.find_element_by_xpath('select'))
    #打印已选中的文本
  print select_element.all_selected_options[0].text
    return select_element.select_by_value(value)


1.2 Excel操作的封装-----Excel.py

由于用的是数据驱动框架类型,这里我使用excel来读取测试数据、记录测试结果,那么就避免不了excel的大量操作,所以把excel的大部分操作封装起来,后续调用---我常用的excel操作是查询和插入,见代码:


#encoding=utf-8
from openpyxl import Workbook
from openpyxl import load_workbook
from ProjectVar.Var import *
from openpyxl.styles import Border,Side,Font

class Excel(object):
    def __init__(self):
        self.font=Font(color=None)
        self.colorDict={'red':'FFFF3030','green':'FF008B00'}
    #test_path表示excel的路径,在另外一个package里面封装的,封装的内容有工程目录的绝对路径,是公用的,该工程目录下的其他文件路径只要在此基础上拼接字符串即可
        self.wb=load_workbook(test_path)
    #表示默认选中的是第一个表格
     self.ws=self.wb.active

    def rename(self,new_name):
        #给表格重命名
    self.ws.title=new_name
        self.wb.save(test_path)

    def GetSheetName(self):
        #获取所有表格名称
    return self.wb.get_sheet_names()

    def GetSheetByName(self,sheet_name):
        #通过表格名称获取表格
    self.ws=self.wb.get_sheet_by_name(sheet_name)
        return self.ws

    def GetCurrentSheetName(self):
        #获取当前表格名称
    return self.ws.title

    def GetCellContent(self,col_num,row_num):
        #获取单元格内容
    return self.ws.cell(row=row_num,column=col_num).value

    def WriteCellContent(self,col_num,row_num,content):
        #往指定的单元格里面写入内容
    self.ws.cell(row=row_num,column=col_num).value=content
        self.wb.save(test_path)

    def GetMaxRow(self):
        #获取最大行号
    return self.ws.max_row

    def GetMaxColumn(self):
        #获取最大列号
    return self.ws.max_column

1.3 配置文件的基本操作的封装----GetConf.py

GetConf.py主要的功能是用来提取页面元素的定位方式locateType和定位表达式locateExpression的;

代码如下:

#encoding=utf-8
import ConfigParser
from ProjectVar.Var import *

class ParsePageObjectRepositoryConfig(object):
    def __init__(self):
        self.cf=ConfigParser.ConfigParser()
        self.cf.read(page_object_repository_path)

    def getItemsFromSection(self,sectionName):
        items=self.cf.items(sectionName)
        return dict(items)

1.4 Driver.py 得到driver

代码如下:

#encoding=utf-8

from selenium import webdriver

driver=webdriver.Chrome(executable_path='c:\\Python27\\chromedriver')

2、ProjectVar

2.1 将工程中用到的已知元素封装起来,在脚本中直接传递变量名称即可---var.py

见代码:

#encoding=utf-8
import os

#当前文件路径
file_path=__file__
#工程路径
#os.path.dirname(__file__)当前文件所在路径
project_path=os.path.dirname(os.path.dirname(__file__)).decode('utf-8')

test_path=project_path+u'//TestData//126邮箱联系人.xlsx'

page_object_repository_path=project_path+'//Conf//PageObjectRepository .ini'

url='http:\\www.126.com'

3、Conf(配置文件)

3.1 页面元素的路径全部封装在配置文件PageObjectRepository.ini中,这样即使路径变更不会直接修改代码,减少了维护成本;----PageObjectRepository .ini

这里将要操作的页面元素的定位路径全都写在这个配置文件,按照页面来写,每个操作页面的写在不同的标签栏里面;

本次例子需要的页面元素如下:

[configparse操作配置文件的时候有坑]
[ini中的内容要全部小写,否则读取出来的时候会自动转换成小写,这样就会发生匹配不上的情况]

[126mail_login]
loginpage.frame=xpath>//iframe[@id='x-URS-iframe']
loginpage.username=xpath>//span[.='@126.com']//preceding-sibling::input
loginpage.password=xpath>//label[.='密码']//following-sibling::input[2]
loginpage.loginbutton=xpath>//a[@id='dologin']

[126mail_homepage]
home_age.addressbook=xpath>//div[text()='通讯录']

[126mail_addcontactspage]
addcontacts_page.create_contacts_btn=xpath>//span[text()='新建联系人']
addcontacts_page.contact_person_name=xpath>//a[@title='编辑详细姓名']/preceding-sibling::div/input
addcontacts_page.contact_person_email=xpath>//*[@id='iaddress_MAIL_wrap']//input
addcontacts_page.star_contacts=xpath>//span[text()='设为星标联系人']/preceding-sibling::span/b
addcontacts_page.contact_person_mobile=xpath>//*[@id='iaddress_TEL_wrap']//dd//input
addcontacts_page.contact_person_comment=xpath>//textarea
addcontacts_page.save_contace_person=xpath>//span[.='确 定']

4 、PageObject(获取页面元素)
此次例子分为登录、首页-通讯录、添加联系人三个步骤
4.1 登录页面的元素获取----login_page.py
#encoding=utf-8
from ProjectVar.Var import *
from Util.GetConf import *
from Util.ObjectMap import *
from Util.Driver import *

class LoginPage(object):
    def __init__(self):
        self.cf=ParsePageObjectRepositoryConfig()
        #section需要修改
    self.login_page_items=self.cf.getItemsFromSection('126mail_login')#得到的是字典

    def iframe(self):
        #获取iframe
        locateType=self.login_page_items['loginpage.frame'].split('>')[0]
        locateExpression=self.login_page_items['loginpage.frame'].split('>')[1]
        return getEelement(driver,locateType,locateExpression)

    def username(self):
        #获取iframe
        locateType=self.login_page_items['loginpage.username'].split('>')[0]
        locateExpression=self.login_page_items['loginpage.username'].split('>')[1]
        return getEelement(driver,locateType,locateExpression)

    def password(self):
        #获取iframe
        locateType=self.login_page_items['loginpage.password'].split('>')[0]
        locateExpression=self.login_page_items['loginpage.password'].split('>')[1]
        return getEelement(driver,locateType,locateExpression)

    def login_button(self):
        #获取iframe
        locateType=self.login_page_items['loginpage.loginbutton'].split('>')[0]
        locateExpression=self.login_page_items['loginpage.loginbutton'].split('>')[1]
        return getEelement(driver,locateType,locateExpression)

4.2首页,通讯录元素获取---home_page.py
#encoding=utf-8
from ProjectVar.Var import *
from Util.GetConf import *
from Util.ObjectMap import *
from Util.Driver import *

class HomePage(object):
    def __init__(self):
        self.cf=ParsePageObjectRepositoryConfig()
        #section需要修改
        self.login_page_items=self.cf.getItemsFromSection('126mail_homepage')

    def addressbook(self):
        #获取addressbook
        locateType=self.login_page_items['home_age.addressbook'].split('>')[0]
        locateExpression=self.login_page_items['home_age.addressbook'].split('>')[1]
        print locateExpression,locateType
        return getEelement(driver,locateType,locateExpression)

4.3添加联系人页面元素获取----address_book.py
#encoding=utf-8
from ProjectVar.Var import *
from Util.GetConf import *
from Util.ObjectMap import *
from Util.Driver import *

class AddressBook(object):
    def __init__(self):
        self.cf=ParsePageObjectRepositoryConfig()
        #section需要修改
    self.login_page_items=self.cf.getItemsFromSection('126mail_addcontactspage')

    def AddContactsButton(self):
        #获取addressbook
        locateType=self.login_page_items['addcontacts_page.create_contacts_btn'].split('>')[0]
        locateExpression=self.login_page_items['addcontacts_page.create_contacts_btn'].split('>')[1]
        print locateExpression,locateType
        return getEelement(driver,locateType,locateExpression)

    def PersonName(self):
        #联系人名字
    locateType=self.login_page_items['addcontacts_page.contact_person_name'].split('>')[0]
        locateExpression=self.login_page_items['addcontacts_page.contact_person_name'].split('>')[1]
        print locateExpression,locateType
        return getEelement(driver,locateType,locateExpression)

    def Email(self):
        #联系人邮箱
    locateType=self.login_page_items['addcontacts_page.contact_person_email'].split('>')[0]
        locateExpression=self.login_page_items['addcontacts_page.contact_person_email'].split('>')[1]
        print locateExpression,locateType
        return getEelement(driver,locateType,locateExpression)

    def Star(self):
        #星级联系人
    locateType=self.login_page_items['addcontacts_page.star_contacts'].split('>')[0]
        locateExpression=self.login_page_items['addcontacts_page.star_contacts'].split('>')[1]
        print locateExpression,locateType
        return getEelement(driver,locateType,locateExpression)

    def Mobile(self):
        #电话
    locateType=self.login_page_items['addcontacts_page.contact_person_mobile'].split('>')[0]
        locateExpression=self.login_page_items['addcontacts_page.contact_person_mobile'].split('>')[1]
        print locateExpression,locateType
        return getEelement(driver,locateType,locateExpression)

    def Comment(self):
        #备注
    locateType=self.login_page_items['addcontacts_page.contact_person_comment'].split('>')[0]
        locateExpression=self.login_page_items['addcontacts_page.contact_person_comment'].split('>')[1]
        print locateExpression,locateType
        return getEelement(driver,locateType,locateExpression)

    def Save(self):
        #保存
    locateType=self.login_page_items['addcontacts_page.save_contace_person'].split('>')[0]
        locateExpression=self.login_page_items['addcontacts_page.save_contace_person'].split('>')[1]
        print locateExpression,locateType
        return getEelement(driver,locateType,locateExpression)


5、 TestData ----数据和结果excel表格(数据驱动)



到目前为止,我的目录结构是这样的:





本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Python-基于数据驱动模式的自动化测试框架搭建的的逐步实现(二) 的相关文章

  • 如何在Python的SciPy中更改稀疏矩阵中的元素?

    我构建了一个小代码 我想用它来解决涉及大型稀疏矩阵的特征值问题 它工作正常 我现在要做的就是将稀疏矩阵中的一些元素设置为零 即最顶行中的元素 对应于实现边界条件 我可以调整下面的列向量 C0 C1 和 C2 来实现这一点 不过我想知道是否有
  • 如何在 Windows 64 上安装 NumPy?

    NumPy 安装程序在注册表中找不到 python 路径 无法安装 需要 Python 2 5 版本 但在注册表中未找到该版本 OK 我必须修改注册表吗 我已经修改了 PATH 以指向Python25安装目录 我可以检查一下您使用的是什么安
  • 使用 matplotlib 从“列表列表”绘制 3D 曲面

    我已经搜索了一些 虽然我可以找到许多有用的网格网格示例 但没有一个清楚地表明我如何将列表列表中的数据转换为可接受的形式 以适应我所讨论的各种方式 当谈到 numpy matplotlib 以及我所看到的建议的术语和步骤顺序时 我有点迷失 我
  • Sublime Text 插件开发中的全局 Python 包

    一 总结 我不知道 Sublime Text 插件开发人员如何使用 Sublime Text 查找全局 Python 包 而不是 Sublime Text 目录的 Python 包 Sublime Text使用自己的Python环境 而不是
  • opencv水印周围的轮廓

    我想在图像中的水印周围画一个框 我已经提取了水印并找到了轮廓 但是 不会在水印周围绘制轮廓 轮廓是在我的整个图像上绘制的 请帮我提供正确的代码 轮廓坐标的输出为 array 0 0 0 634 450 634 450 0 dtype int
  • 使用 python 中的公式函数使从 Excel 中提取的值的百分比相等

    import xlrd numpy excel Users Bob Desktop wb1 xlrd open workbook excel assignment3 xlsx sh1 wb1 sheet by index 0 colA co
  • Kivy - 有所有颜色名称的列表吗?

    在 Kivy 中 小部件 color属性允许输入其值作为字符串颜色名称 也 例如在 kv file Label color red 是否有所有可能的颜色名称的列表 就在这里 来自Kivy 的文档 https kivy org doc sta
  • 如何在 Python 中加密并在 Java 中解密?

    我正在尝试在 Python 程序中加密一些数据并将其保存 然后在 Java 程序中解密该数据 在Python中 我像这样加密它 from Crypto Cipher import AES KEY 1234567890123456789012
  • Geodjango距离查询未检索到正确的结果

    我正在尝试根据地理位置的接近程度来检索一些帖子 正如您在代码中看到的 我正在使用 GeoDjango 并且代码在视图中执行 问题是距离过滤器似乎被完全忽略了 当我检查查询集上的距离时 我得到了预期距离 1m 和 18km 但 18km 的帖
  • Matplotlib 中 x 轴标签的频率和旋转

    我在下面编写了一个简单的脚本来使用 matplotlib 生成图形 我想将 x tick 频率从每月增加到每周并轮换标签 我不知道从哪里开始 x 轴频率 我的旋转线产生错误 TypeError set xticks got an unexp
  • 使用 Pandas 计算 delta 列

    我有一个数据框 如下所示 Name Variable Field A 2 3 412 A 2 9 861 A 3 5 1703 B 3 5 1731 A 4 0 2609 B 4 0 2539 A 4 6 2821 B 4 6 2779 A
  • Python:IndexError:修改代码后列表索引超出范围

    我的代码应该提供以下格式的输出 我尝试修改代码 但我破坏了它 import pandas as pd from bs4 import BeautifulSoup as bs from selenium import webdriver im
  • 返回表示每组内最大值的索引的一系列数字位置

    考虑一下这个系列 np random seed 3 1415 s pd Series np random rand 100 pd MultiIndex from product list ABDCE list abcde One Two T
  • 在 keras 中保存和加载权重

    我试图从我训练过的模型中保存和加载权重 我用来保存模型的代码是 TensorBoard log dir output model fit generator image a b gen batch size steps per epoch
  • SocketIO + Flask 检测断开连接

    我在这里有一个不同的问题 但意识到它可以简化为 如何检测客户端何时从页面断开连接 关闭其页面或单击链接 换句话说 套接字连接关闭 我想制作一个带有更新用户列表的聊天应用程序 并且我在 Python 上使用 Flask 当用户连接时 浏览器发
  • 从 NumPy 数组到 Mat 的 C++ 转换 (OpenCV)

    我正在围绕 ArUco 增强现实库 基于 OpenCV 编写一个薄包装器 我试图构建的界面非常简单 Python 将图像传递给 C 代码 C 代码检测标记并将其位置和其他信息作为字典元组返回给 Python 但是 我不知道如何在 Pytho
  • 在 Django 查询中使用 .extra(select={...}) 引入的值上使用 .aggregate() ?

    我正在尝试计算玩家每周玩游戏的次数 如下所示 player game objects extra select week WEEK games game date aggregate count Count week 但姜戈抱怨说 Fiel
  • Django Admin 中的反向内联

    我有以下 2 个型号 现在我需要将模型 A 内联到模型 B 的页面上 模型 py class A models Model name models CharField max length 50 class B models Model n
  • 如何与其他用户一起使用 pyenv?

    如何与其他用户一起使用 pyenv 例如 如果我在用户 test 的环境中安装了 pyenv 则当我以 test 身份登录时可以使用 pyenv 但是 当我以其他用户 例如 root 身份登录时如何使用 pyenv 即使你这么做了 我也会s
  • TKinter 中的禁用/启用按钮

    我正在尝试制作一个像开关一样的按钮 所以如果我单击禁用按钮 它将禁用 按钮 有效 如果我再次按下它 它将再次启用它 我尝试了 if else 之类的东西 但没有成功 这是一个例子 from tkinter import fenster Tk

随机推荐