混合驱动测试框架源码:https://download.csdn.net/download/qq_38175040/18632633
之前的前七篇写了数字驱动框架,然后又写了两篇关键字驱动框架
数字驱动框架:侧重于单个接口或者单个功能的测试,重复自动化输入多组数据
关键字驱动框架:侧重于自动化一套完整的流程
关键字驱动框架的篇幅比较少,因为其中的大多数只是在数字驱动框架里都已经用过了。
在这边大概还是用两篇的篇幅讲一下混合驱动框架,就是中间有直接走流程的部分,也有多组数据测试一个功能或接口。
一.还是先加一些基本的功能,如Utils,ConfigFiles等通用功能(三个框架都要用到)
新建一个项目,然后创几个通用的包
都是复制的之前的项目的,命名都没有改
接下来这个混合驱动框架,关键字的部分就是走流程,比如登录163邮箱,数据驱动的部分则是以登录进入163邮箱之后的添加联系人功能为例,从excel取数据添加多个联系人。
还是拿前一个项目里的excel表格,做出如下修改,在首个sheet里加上驱动类型以及数据源的sheet名
对excel改动后我们可能会出现同时对多个sheet页进行操作的情况,所以需要对excelOperate.py文件进行修改,之前只支持同时操作一个sheet页(修改思路,sheet不再作为类中定义的属性,而是作为外部属性传入)
对类下面的具体函数进行修改
在main函数里测试一下改造之后的代码是否正确。
运行一下,可以成功获取数据
贴一下改动之后的ExcelOperate.py里的代码;
import openpyxl
from openpyxl import load_workbook
from ConfigFiles.ConfigPath import xlsxPath
class ExcelOperate:
def __init__(self):
self.workbook = None
# self.sheet = None
def load_workbook(self,filename):
'''
加载相应的excel文件
:param filename:
:return:
'''
try:
self.workbook = load_workbook(filename)
except Exception as e:
print(e)
def get_sheet_by_name(self,sheetname):
'''
拿到xlsx文件里对应的页
:param sheetname:
:return:
'''
try:
# 返回某个sheet
return self.workbook[sheetname]
except Exception as e:
print(e)
def get_rows_nums(self,sheet):
'''
返回当前页的最大行数
:return:
'''
return sheet.max_row
def get_col_nums(self,sheet):
'''
获取最大列数
:return:
'''
return sheet.max_column
def get_row_values(self,row,sheet):
'''
根据row获取某一行的值
:param row:
:return:
'''
columns = sheet.max_column
row_data = []
#遍历列的时候从1开始,不是从0开始,因为xlsx没有第0行,第0列
for i in range(1,columns+1):
cell_value = sheet.cell(row = row,column = i).value
row_data.append(cell_value)
return row_data
def get_cell_value(self,row,column,sheet):
'''
获取某一个单元格的值
:param row:
:param column:
:return:
'''
cell_value = sheet.cell(row=row,column=column).value
return cell_value
def modify_cell(self,row,column,data,sheet):
'''
在单元格内写入数据
:param row:
:param column:
:param data:
:return:
'''
sheet.cell(row=row,column=column).value = data
self.workbook.save(xlsxPath)
if __name__ == '__main__':
eo = ExcelOperate()
#根据名字读取xlsx文件,xlsxPath已经在ConfigPath.py文件中定义过了
eo.load_workbook(xlsxPath)
sheet = eo.get_sheet_by_name('测试用例')
print(eo.get_col_nums(sheet))
print(eo.get_rows_nums(sheet))
print(eo.get_row_values(2,sheet))
print(eo.get_cell_value(2,7,sheet))
# eo.modify_cell(2,7,'dew')
二.实现添加多个联系人功能
这个功能需要两个sheet页,分别是使用了关键字驱动和数据驱动
新建一个文件,并写入添加联系人的函数,因为从始至终都只要对一个excel进行操作,所以将excel作为参数传入函数中,不要在函数内申明excel(可能被多次调用从而创建多个实例),data_sheet和step_sheet就是要操作的两个sheet
还是老一套,先读取excel里的各项数据
测试一下能否得到数据,测试代码可以照搬ExcelOperate.py里的main函数下的代码
获取成功
---------------------------------------------------------------------------------------------------------------------------------------------------------
忘了说要先把step sheet准备好,也就是
还是老样子,先写个线性流程确保添加联系人能走通
添加成功
贴一下代码
import time
from selenium import webdriver
driver = webdriver.Chrome()
driver.get('https://mail.163.com/')
driver.maximize_window()
iframe = driver.find_element_by_tag_name('iframe')
driver.switch_to.frame(iframe)
driver.find_element_by_name('email').send_keys('lsqtester001')
driver.find_element_by_name('password').send_keys('qwer123')
driver.find_element_by_id('dologin').click()
time.sleep(2)
# 添加联系人
driver.find_element_by_id('_mail_tabitem_1_119text').click()
time.sleep(2)
driver.find_element_by_xpath('/html/body/div[2]/div[1]/div[2]/header/div/div[1]/div/span[2]').click()
time.sleep(2)
driver.find_element_by_id('input_N').send_keys('孙悟空')
driver.find_element_by_xpath('/html/body/div[8]/div[2]/div/div/div[1]/div/div[1]/div[1]/dl/dd/div/input').send_keys('1234562@163.com')
driver.find_element_by_xpath('/html/body/div[8]/div[2]/div/div/div[1]/div/div[1]/dl[2]/dd/span/span[1]/b').click()
driver.find_element_by_xpath('/html/body/div[8]/div[2]/div/div/div[1]/div/div[1]/div[2]/dl/dd/div/input').send_keys('13455667788')
driver.find_element_by_xpath('/html/body/div[8]/div[2]/div/div/div[1]/div/div[1]/dl[3]/dd/div/textarea').send_keys('这是备注')
driver.find_element_by_xpath('/html/body/div[8]/div[3]/div[2]/div[1]/span').click()
然后根据代码将step shee里的定位表达式t补全
---------------------------------------------------------------------------------------------------------------------------------------------------------
接下来获取操作步骤sheet里的数据,这一部分的代码和上面一样,可以获取数据
然后我们希望根据${name},来到data sheet中获取name值
代码如下,根据获取到的${name},提取到其中的name,又因为name这个变量早就在上面获取data sheet的时候被赋值过了,那么就自然而然地拿到了data sheet中的name值
运行一下,确实是拿到了data sheet中的数据
数据都拿到了接下来构建函数表达式,可以到上一个关键字驱动框架里去抄这一段代码
可以正常执行,获取函数表达式成功
这边的函数和之前的关键字驱动框架的函数有点不同,比如click函数,有的click函数可能携带两个以上的参数
这时候回到elementAction.py里去查看函数,之前创建这里的函数时多传入了一个参数args,所以当这里有click函数传入了三个参数时,这个args就派上了用场,我们不需要重写click函数也能继续执行代码,不会报错。(之前关键字驱动框架没有说这个参数的作用,这里碰到了)
我们可以就在获得函数表达式那里判断,如果传入三个参数的click,第三个参数为不收藏联系人,那么这个click函数就不执行。其他情况下都需要执行函数。
最后写一个伪断言,如果执行成功的步骤数等于总步骤数,则添联系人成功(这一步不太重要,也可以用assert断言来写)。
最后贴一下代码,这部分代码是混合驱动框架的核心
from ConfigFiles.ConfigPath import xlsxPath
from Utils.ExcelOperate import ExcelOperate
from Action.elementAction import *
def add_person(excel,data_sheet,step_sheet):
'''
添加联系人
:param excel:
:param data_sheet:
:param step_sheet:
:return:
'''
try:
# 获取数据源行数
data_row_nums = excel.get_rows_nums(data_sheet)
# 获取步骤行数
step_row_nums = excel.get_rows_nums(step_sheet)
# 记录step_sheet成功的行数,若全部成功,则代表添加联系人成功
success_record = 0
# data_sheet里数据需要执行的行数
need_record = 0
# 读取数据源
for i in range(2,data_row_nums+1):
# 判断此条数据是否需要执行
if excel.get_cell_value(i,6,data_sheet) == 'y':
need_record += 1
# 获取该行各单元格的数据
name = excel.get_cell_value(i,1,data_sheet)
mail = excel.get_cell_value(i,2,data_sheet)
phone = excel.get_cell_value(i,3,data_sheet)
is_star = excel.get_cell_value(i,4,data_sheet)
remark = excel.get_cell_value(i,5,data_sheet)
# 记录执行成功的步骤数
for j in range(2,step_row_nums+1):
# 获取执行步骤内的各项数据
step_desc = excel.get_cell_value(j,2,step_sheet)
key_word = excel.get_cell_value(j,3,step_sheet)
location_type = excel.get_cell_value(j,4,step_sheet)
location_key = excel.get_cell_value(j,5,step_sheet)
operate_value = excel.get_cell_value(j,6,step_sheet)
# 当操作之operate_value的形式如同${xxx}用数据源中的xxx来替换掉
if isinstance(operate_value,str) and '$' in operate_value and '{' in operate_value and '}' in operate_value:
# 做一个切片操作,截取字符串的第三位到倒数第二位
operate_value = eval(operate_value[2:-1])
# 构建函数表达式
method_express = ''
if operate_value and location_type is None and location_key is None:
if isinstance(operate_value, int):
method_express = key_word + "(" + str(operate_value) + ")"
else:
method_express = key_word + "('" + operate_value + "')"
# 只有关键字不为空
if location_type is None and location_key is None and operate_value is None:
method_express = key_word + "(" + ")"
# 只有操作值为空
if operate_value is None and location_key and location_type:
method_express = key_word + "('" + location_type + "'" + "," + "'" + location_key + "')"
# 都不为空
if operate_value and location_type and location_key:
if isinstance(operate_value, int):
method_express = key_word + "('" + location_type + "'" + "," + "'" + location_key + "'" + "," + str(
operate_value) + ")"
else:
method_express = key_word + "('" + location_type + "'" + "," + "'" + location_key + "'" + "," + "'" + operate_value + "')"
# 执行上面构造的函数
# print(method_express)
if operate_value != '不收藏联系人':
# 执行click函数
print(method_express)
success_record += 1
else:
success_record += 1
# 如果执行成功步骤数 == 总步骤数,代表添加联系人成功
if success_record +1 == step_row_nums:
excel.modify_cell(i,7,'添加联系人成功',data_sheet)
print('添加就诊人成功')
success_record = 0
except Exception as e:
print(e)
if __name__ == '__main__':
excel = ExcelOperate()
excel.load_workbook(xlsxPath)
data_sheet = excel.get_sheet_by_name('add_person')
step_sheet = excel.get_sheet_by_name('contract')
add_person(excel,data_sheet,step_sheet)
--------------------------------------------------------------------------------------------------------------------------------------------------------
最后在回顾一下思路,首先我们读取data sheet里的数据:
如果is_executed为y则代表这条数据需要执行,紧接着读取step sheet里的步骤来操作这行数据
step里通过操作值${}来获取data sheet里的数据
有了数据,有了操作步骤,接下来就是效仿关键字驱动框架来生成函数表达式
我们暂时无法执行,因为还没有登录邮箱,这部分代码仅仅是添加联系人的测试用例,需要以登录为前提。
不过函数表达式能写出来,这部分代码的功能就已经完成了。