自动化测试经常使用csv文件进行数据驱动测试,读写方法总结如一下
第1步: 学会读取CSV文件
'''
Created on 2018年3月1日
@author: Yvon_早安阳光
'''
import csv
# 读取csv文件方式1
csvfile = open('shuju.csv','r')
reader = csv.reader(csvfile)#返回的是迭代类型
data =[] #中括号[]代表list列表数据类型,列表是一种可变的序列
for item in reader:
print(item)
data.append(item)
print(data)
csvfile.close()
print('-------------------------------------------------------------------------------------------------------')
#读取csv文件方式2
with open ('shuju.csv','r') as csvfile:
reader1 = csv.reader(csvfile)#返回的是迭代类型
for item1 in reader1:
print(item1) #打印所有的数据
colum = [item1[2]] #获取第3列
print(colum)
csvfile.close()
print('-------------------------------------------------------------------------------------------------------')
#读取csv文件方式3
'''
使用DictReader,和reader函数类似,接收一个可迭代的对象,能返回一个生成器,
但是返回的每一个单元格都放在一个字典的值内,而这个字典的键则是这个单元格的标题(即列头)
'''
with open('shuju.csv','r') as csvfile2:
reader2 = csv.DictReader(csvfile2)
colum = [row for row in reader2]
colum1 = [row['语言'] for row in colum]
print(colum)
print(colum1)
第2步:学会写入CSV文件
'''
Created on 2018年3月2日
@author: fajin
'''
import pandas as pd
#写入csv文件方式1--使用Pandas模块
name = ["序号","语言","测试工具"]
list = [['1','VB','QTP'],['2','Python','Appium手机'],['3','日本Ruby','Selenium']]
# test = pd.DataFram(columns = name,data = list)
test = pd.DataFrame(columns = name,data = list)
test.to_csv('shuju1.csv',index=False,sep=',',encoding="gb2312")#避免中文乱码
print('--------------------------------------------------------')
import csv
#写入csv文件方式2---从列表写入csv文件
#读取csv文件,写入新的csv文件
csvfile = open('shuju.csv','r')
reader = csv.reader(csvfile)#返回的是迭代类型
data =[] #中括号[]代表list列表数据类型,列表是一种可变的序列
for item in reader:
data.append(item)
print(data)
csvfile.close()
csvFile2 = open('shuju2.csv','w', newline='') # 设置newline,否则两行之间会空一行
writer = csv.writer(csvFile2)
m = len(data)
for i in range(m):
writer.writerow(data[i])
csvFile2.close()
#写入csv文件方式3---从字典写入csv文件 貌似适合2列
dic = {"序号":["语言","测试工具"]}
csvFile3 = open('shuju3.csv','w', newline='')
writer2 = csv.writer(csvFile3)
for key in dic:
writer2.writerow([key, dic[key]])
csvFile3.close()
第3步: 实战Excel数据驱动自动化测试
Excel数据驱动维护测试用例
ExcelConfig.py 脚本文件 定义Header头
# -*- coding: utf-8 -*-
# @Time : 2020/12/1 20:52
# @File : ExcelConfig.py
# @Author : Yvon_₯㎕ζ๓
#定义类
class DataConfig:
#定义列属性
#用例ID 模块 接口名称 请求URL 前置条件 请求类型 请求参数类型
#请求参数 预期结果 实际结果 备注 是否运行 headers cookies status_code 数据库验证
#用例ID
case_id = "用例ID"
case_model = "模块"
case_name = "接口名称"
url = "请求URL"
pre_exec = "前置条件"
method = "请求类型"
params_type = "请求参数类型"
params = "请求参数"
expect_result = "预期结果"
actual_result = "实际结果"
is_run = "是否运行"
headers = "headers"
cookies = "cookies"
code = "status_code"
db_verify = "数据库验证"
ExcelUtil 读写Excel文件
# -*- coding: utf-8 -*-
# @Time : 2020/11/26 17:43
# @File : ExcelUtil.py
# @Author : Yvon_懿払曦
import os
import xlrd ,json
from config.Conf import ConfigYaml
from config import Conf
#目的:参数化,pytest list文件形式读取
# 自定义异常
class SheetTypeError:
pass
#1、验证文件是否存在,存在读取,不存在报错
class ExcelReader:
def __init__(self,excel_file,sheet_by):
if os.path.exists(excel_file):
self.excel_file = excel_file
self.sheet_by = sheet_by
self._data = list()
else:
raise FileNotFoundError("文件不存在")
#2、读取sheet方式.名称,索引
def data(self):
# 存在不读取,不存在读取
if not self._data:
workbook = xlrd.open_workbook(self.excel_file)
if type(self.sheet_by) not in [str,int]:
raise SheetTypeError("请输入int or str")
elif type(self.sheet_by) == int:
sheet = workbook.sheet_by_index(self.sheet_by) # int型
elif type(self.sheet_by) == str:
sheet = workbook.sheet_by_name(self.sheet_by) # str型
#3、sheet内容
# 返回list,元素:字典
#格式[{'company': '可口可乐', 'manager': 'Shirley'}, {'company': '北极光', 'manager': 'marry'}]
#1.获取首行信息
title = sheet.row_values(0)
#2.遍历测试行,与首行组成dict,放在list
#1.循环,过滤首行,从1开始
for col in range(1,sheet.nrows):
col_value = sheet.row_values(col)
#2.与首行组成字典,放list
self._data.append(dict(zip(title, col_value)))
#4、返回结果
return self._data
if __name__ == "__main__":
case_file = os.path.join(Conf.get_data_path(), ConfigYaml().get_excel_file()) # 拼接路径+文件
# print(case_file)
# 2).测试用例sheet名称
sheet_name = ConfigYaml().get_excel_sheet()
reader = ExcelReader(case_file,sheet_name)
# reader = ExcelReader("../data/testdata.xlsx", "美多商城接口测试")
result = reader.data()
# print(result)
print(json.dumps(result, sort_keys=True, ensure_ascii=False, indent=4, separators=(', ', ': '))) # Json格式打印
ExcelData.py脚本读取有效测试用例
- 根据运行列是否==y,获取测试用例
- 获取全部的测试用例
- 从获取全部的测试用例中获取前置条件测试用例
# -*- coding: utf-8 -*-
# @Time : 2020/11/27 20:17
# @File : ExcelData.py
# @Author : Yvon_懿払曦
from utils.ExcelUtil import ExcelReader
# import json
from common.ExcelConfig import DataConfig
class Data:
def __init__(self,case_file,sheet_name):
#1、使用excel工具类,获取结果list
# self.reader = ExcelReader("../data/testdata.xlsx","美多商城接口测试")
self.reader = ExcelReader(case_file, sheet_name) #文件名、sheet_name参数化
#2、列是否运行内容,y
def get_run_data(self):
"""
根据运行列是否==y,获取测试用例
:return:
"""
run_list = list()
for line in self.reader.data():
#if line[DataConfig.is_run] == "y":
if str(line[DataConfig().is_run]).lower() == "y": #大小写转换Y
# print(line)
#print(json.dumps(line, sort_keys=True, ensure_ascii=False, indent=4, separators=(', ', ': '))) # Json格式打印
run_list.append(line)
# print(json.dumps(run_list, sort_keys=True, ensure_ascii=False, indent=4, separators=(', ', ': '))) # Json格式打印
return run_list
def get_case_list(self):
"""
获取全部的测试用例
:return:
"""
#方法一
# run_list = list()
# for line in self.reader.data():
# run_list.append(line)
# return run_list
# 方法二 列表推导
run_list = [line for line in self.reader.data()]
return run_list
def get_case_pre(self,pre):
#获取全部测试用例
#list判断、执行、获取
"""
根据前置条件:从全部测试用例取到测试用例
:param pre:
:return:
"""
run_list = self.get_case_list()
for line in run_list:
if pre in dict(line).values():
return line
return None
执行test_excel_case.py脚本
从Excel中读取测试用例,做到数据分离,代码中维护参数即可,所有测试数据在Excel中维护
# -*- coding: utf-8 -*-
# @Time : 2020/12/2 11:21
# @File : test_excel_case.py
# @Author : Yvon_₯㎕ζ๓
from config.Conf import ConfigYaml
from config import Conf
from common.ExcelData import Data
from common.ExcelConfig import DataConfig
from common import ExcelConfig
from common import Base
from utils.RequestsUtil import Request
from utils.AssertUtil import AssertUtil
from utils.LogUtil import my_log
import os,json,pytest
import allure
#1、初始化信息
#1).初始化测试用例文件
case_file = os.path.join(Conf.get_data_path(),ConfigYaml().get_excel_file()) # 拼接路径+文件
# print(case_file)
#2).测试用例sheet名称
sheet_name = ConfigYaml().get_excel_sheet()
# print(sheet_name)
#3).获取运行测试用例列表
data_init = Data(case_file,sheet_name)
run_list = data_init.get_run_data()
print(run_list)
# print(json.dumps(run_list, sort_keys=True, ensure_ascii=False, indent=4, separators=(', ', ': '))) # Json格式打印
#4).日志
log = my_log()
#初始化DataConfig
# data_key = DataConfig()
data_key = ExcelConfig.DataConfig
#2、测试用例方法、参数化运行
#先用一个用例去调试
class TestExcel:
def run_api(self,url,method,params=None,header=None,cookie=None):
"""
发送请求api
:return:
"""
# 接口请求
request = Request()
# params 转义json
#验证params 有没有内容
if len(str(params).strip()) != 0:
params = json.loads(params)
#method post/get
if str(method).lower()=="get":
#增加headers,cookies
res = request.get(url,json = params,headers = header,cookies = cookie)
elif str(method).lower()=="post":
res = request.post(url, json=params,headers = header,cookies = cookie)
else:
log.error("错误请求method: %S"% method)
# print(res)
return res
def run_pre(self,pre_case):
"""
前置条件运行
:param pre_case:
:return:
"""
pass
url = ConfigYaml().get_conf_url() + pre_case[data_key.url]
method = pre_case[data_key.method]
params = pre_case[data_key.params]
headers = pre_case[data_key.headers]
cookies = pre_case[data_key.cookies]
header = Base.json_parse(headers)
cookie = Base.json_parse(cookies)
res = self.run_api(url,method,params,header)
print("前置用例执行: %s"%res)
return res
#1).初始化信息url,data
#1、增加pytest
@pytest.mark.parametrize("case",run_list)
#2、修改方法参数
def test_run(self,case):
#run_list 第一个用例,用例,key获取values
url = ConfigYaml().get_conf_url() +case[data_key.url]
print(url)
case_id = case[data_key.case_id]
# print(case_id)
case_model = case[data_key.case_model]
case_name = case[data_key.case_name]
pre_exec = case[data_key.pre_exec]
method = case[data_key.method]
params_type = case[data_key.params_type]
params = case[data_key.params]
expect_result = case[data_key.expect_result]
headers = case[data_key.headers]
cookies = case[data_key.cookies]
code = case[data_key.code]
db_verify = case[data_key.db_verify]
#动态headers请求
##1.验证前置条件
if pre_exec:
pass
##2.找到执行用例
pre_case = data_init.get_case_pre(pre_exec)
print("前置条件信息为: %s" %pre_case)
pre_res = self.run_pre(pre_case)
headers,cookies = self.get_correlation(headers,cookies,pre_res)
header = Base.json_parse(headers)
cookie = Base.json_parse(cookies)
res = self.run_api(url, method, params, header, cookie)
print("测试用例执行: %s" % res)
# return res # 注意
# sheet名称--feature 一级标签
allure.dynamic.feature(sheet_name)
# 模块--story 二级标签
allure.dynamic.story(case_model)
# 用例ID + 接口名称 - - title
allure.dynamic.title(case_id+case_name)
#请求URL 请求类型 期望结果 实际结果 description
# allure.dynamic.description(url+method+expect_result+res)
desc = "请求URL: {}
" \
"请求类型: {}
" \
"期望结果: {}
" \
"实际结果: {}".format(url, method, expect_result, res)
allure.dynamic.description(desc)
#1.断言验证
#2.状态码,返回结果内容,数据库相关结果验证
#"""断言验证--状态码,返回结果内容,数据库相关的结果的验证"""
#1.)状态码
assert_util = AssertUtil()
assert_util.assert_code(int(res["code"]),int(code))
#2.)返回结果内容验证
assert_util.assert_in_body(str(res["body"]),str(expect_result))
#********数据库结果断言********
Base.assert_db("db_1",res["body"],db_verify)
def get_correlation(self,headers,cookies,pre_res):
"""
关联
:param headers:
:param cookies:
:param pre_res:
:return:
"""
#验证是否有关联
headers_para,cookies_para = Base.params_find(headers,cookies)
#有关联,执行前置用例,获取结果
if len(headers_para):
headers_data = pre_res["body"][headers_para[0]]
#结果替换
headers = Base.res_sub(headers,headers_data)
#有关联,执行前置用例,获取结果
if len(cookies_para):
cookies_data = pre_res["body"][cookies_para[0]]
#结果替换
cookies = Base.res_sub(headers,cookies_data)
return headers, cookies
if __name__ == "__main__":
# pass
# TestExcel().test_run()
# pytest.main(["-s","test_excel_case.py"])
report_path = Conf.get_report_path()+os.sep+"result"
report_html_path = Conf.get_report_path()+os.sep+"html"
pytest.main(["-s", "test_excel_case.py", "--alluredir", report_path ])
# Base.allure_report(report_path, report_html_path)
# Base.send_mail(title="接口测试报告结果", content=report_html_path)