1、excel用例设计
用例ID | 模块 | 接口名称 | 请求URL | 前置条件 | 请求类型 | 请求参数类型 | 请求参数 | 预期结果 | 实际结果 | 备注 | 是否运行 | headers | cookies | status_code | 数据库验证 |
login_1 | 登录 | 登录参数为空 | /authorizations/ | POST | json | 无效数据。期待为字典类型 | n | 400 | |||||||
login_2 | 登录 | 登录名为空 | /authorizations/ | POST | json | {"username":"","password":"12345678"} | username': ['该字段不能为空。'] | n | 400 | ||||||
login_3 | 登录 | 登录名或密码为空 | /authorizations/ | POST | json | {"username":"","password":""} | password': ['该字段不能为空。'] | n | 400 | ||||||
login_4 | 登录 | 登录成功 | /authorizations/ | POST | json | {"username":"python","password":"12345678"} | user_id': 1, 'username': 'python' | n | 200 | ||||||
login_5 | 登录 | 登录用户名或密码错误 | /authorizations/ | POST | json | {"username":"python","password":"test123"} | 无法使用提供的认证信息登录 | n | 400 | ||||||
Info_1 | 个人信息 | 个人信息 | /user/ | get | 身份认证信息未提供 | n | 401 | ||||||||
Info_2 | 个人信息 | 获取个人信息正确 | /user/ | login_4 | get | id': 1, 'username': 'python', 'mobile': '17701397029', 'email': '[email protected]' | y | {"Authorization": "JWT ${token}$"} | 200 | select id,username,mobile,email from tb_users where username='python' | |||||
cate_1 | 商品列表数据 | 商品列表数据正确 | /categories/115/skus/ | get | json | {
"page":"1", "page_size": "10", "ordering": "create_time" } |
n | 200 | |||||||
cart_1 | 购物车 | 添加购物车成功 | /cart/ | login_4 | post | json | {"sku_id": "3","count": "1", "selected": "true"} | sku_id': 3, 'count': 1 | n | {"Authorization": "JWT ${token}$"} | 201 | ||||
order_1 | 订单 | 保存订单 | /orders/ | login_4 | post | json | { "address":"1","pay_method":"1" } | order_id | n | {"Authorization": "JWT ${token}$"} | 201 | ||||
sheet名称 feature 一级标签 | |||||||||||||||
模块 story 二级标签 | |||||||||||||||
用例ID+接口名称 title | |||||||||||||||
请求URL 请求类型 期望结果 实际结果描述 | |||||||||||||||
2、读取excel数据
pip install xlrd==1.2.0
注意:如果直接安装最新xlrd,只能打开xls文件,打开xlsx文件会报错。
# @File : excel_demo.py
# 1、导入包,xlrd
import xlrd
# 2、创建workbook对象
book = xlrd.open_workbook('testdata.xlsx')
# 3、sheet对象
#索引
# sheet = book.sheet_by_index(0)
#名称
sheet = book.sheet_by_name("美多商城接口测试")
# 4、获取行数和列数
rows= sheet.nrows#行数
cols = sheet.ncols#列数
# 5、读取每行的内容
for r in range(rows):
r_values = sheet.row_values(r)
# print(r_values)
# 6、获取每列的内容
for c in range(cols):
c_values = sheet.col_values(c)
# print(c_values)
# 7、读取固定列的内容
print(sheet.cell(1,1))
3、Excel工具类封装
# @File : ExcelUtil.py
import os
from pprint import pprint
import xlrd
# 目的:参数化,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方式,名称or索引
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)
elif type(self.sheet_by) == str:
sheet = workbook.sheet_by_name(self.sheet_by)
# 3、读取sheet内容
#返回list 元素:字典
#格式[{"a":"a1","b":"b1"},{"a":"a2","b":"b2"}]
# 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__':
reader = ExcelReader("../data/testdata.xlsx",0)
pprint(reader.data())
4、excel参数化运行之获取是否运行
获取是否运行
# -*- coding: utf-8 -*-
# @Time : 2021/12/11 20:07
# @Author : jeffky
# @File : ExcelData.py
from pprint import pprint
from common.ExcelConfig import DataConfig
from utils.ExcelUtil import ExcelReader
class Data:
def __init__(self,testcase_file,sheet_name):
#1、使用excel工具类,获取结果list
# self.reader = ExcelReader("../data/testdata.xlsx", 0)
self.reader = ExcelReader(testcase_file, sheet_name)
# pprint(reader.data())
# 2、列是运行内容,y
def get_run_list(self):
'''
根据是否运行==y,会哦去执行测试用例
:return:
'''
run_list= list()
for line in self.reader.data():
if str(line[DataConfig().is_run]).lower() == "y":
# print(line)
# 3、保存要执行结果,放到新的列表。
run_list.append(line)
# pprint(run_list)
return run_list
5、excel参数化运行之参数化运行
excel映射
# @File : ExcelConfig.py
#定义类
class DataConfig:
#定义类属性
#用例ID 模块 接口名称 请求URL 前置条件 请求类型 请求参数类型 请求参数 预期结果 实际结果 备注 是否运行 headers cookies status_code 数据库验证
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='数据库验证'
conf.yml
BASE:
#log等级
log_level: "debug"
#扩展名
log_extension: ".log"
test:
url: "http://211.103.136.242:8064"
case_file: "testdata.xlsx"
case_sheet: "美多商城接口测试"
修改Conf.py
class ConfigYaml:
# 初始化yaml读取配置文件
def __init__(self):
self.config = YamlReader(get_config_file()).data()
self.db_config = YamlReader(get_db_config_file()).data()
# 定义方法获取需要信息
def get_excel_file(self):
'''
获取测试用例excel名称
:return:
'''
return self.config['BASE']['test']['case_file']
def get_excel_sheet(self):
'''
获取测试用例sheet名称
:return:
'''
return self.config['BASE']['test']['case_sheet']
执行单个测试用例
# -*- coding: utf-8 -*-
# @Time : 2021/12/12 3:18
# @Author : jeffky
# @File : test_excel_case.py
import json
from utils.RequestsUtil import Request
from common import ExcelConfig
from utils.LogUtil import my_log
from config.Conf import ConfigYaml, BASE_DIR
from common.ExcelData import Data
import os
# 1、初始化信息
# 1)初始化测试用例文件
conf_read = ConfigYaml()
case_file =os.path.join((BASE_DIR+os.sep+"data"),conf_read.get_excel_file())
# print(case_file)
# 2)测试用例sheet名称
sheet_name = conf_read.get_excel_sheet()
# 3)获取是否都运行测试用例列表
run_list = Data(case_file,sheet_name).get_run_list()
# 4)日志
log = my_log()
# 2、测试用例方法,参数化运行
#一个测试用例的执行
class TestExcel:
# 1)初始化信息,url,data
def test_run(self):
data_key = ExcelConfig.DataConfig
# run_list第1个用例,key获取values
url = conf_read.get_conf_url()+run_list[0][data_key.url]
print("url---->",url)
case_id = run_list[0][data_key.case_id]
case_model=run_list[0][data_key.case_model]
case_name=run_list[0][data_key.case_name]
pre_exec = run_list[0][data_key.pre_exec]
method =run_list[0][data_key.method]
params_type=run_list[0][data_key.params_type]
params=run_list[0][data_key.params]
expect_result = run_list[0][data_key.expect_result]
headers = run_list[0][data_key.headers]
cookies = run_list[0][data_key.cookies]
code = run_list[0][data_key.code]
db_verify=run_list[0][data_key.db_verify]
# 2)接口请求
request = Request()
#params 转义json
# 验证params有没有内容
if len(str(params).strip()) is not 0:
params=json.loads(params)
# method post/getopt
if str(method).lower()=='get':
res = request.get(url,json=params)
elif str(method).lower()=='post':
res = request.post(url,json=params)
else:
log.error("错误请求method--->",method)
print(res)
TestExcel().test_run()
参数化执行测试用例
# -*- coding: utf-8 -*-
# @Time : 2021/12/12 3:18
# @Author : jeffky
# @File : test_excel_case.py
import json
from pprint import pprint
import pytest as pytest
from utils.RequestsUtil import Request
from common import ExcelConfig
from utils.LogUtil import my_log
from config.Conf import ConfigYaml, BASE_DIR
from common.ExcelData import Data
import os
# 1、初始化信息
# 1)初始化测试用例文件
conf_read = ConfigYaml()
case_file =os.path.join((BASE_DIR+os.sep+"data"),conf_read.get_excel_file())
# print(case_file)
# 2)测试用例sheet名称
sheet_name = conf_read.get_excel_sheet()
# 3)获取是否都运行测试用例列表
run_list = Data(case_file,sheet_name).get_run_list()
# 4)日志
log = my_log()
# 2、测试用例方法,参数化运行
class TestExcel:
# 1、增加pytest
# 2、修改方法参数
# 3、重构函数内容
# 4、pytest.main
# 1)初始化信息,url,data
# 1、增加pytest
@pytest.mark.parametrize("case",run_list)
def test_run(self,case):
data_key = ExcelConfig.DataConfig
# run_list第1个用例,key获取values
url = conf_read.get_conf_url()+case[data_key.url]
print("url---->",url)
case_id = case[data_key.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]
# 2)接口请求
request = Request()
#params 转义json
# 验证params有没有内容
if len(str(params).strip()) is not 0:
params=json.loads(params)
# method post/getopt
if str(method).lower()=='get':
res = request.get(url,json=params)
elif str(method).lower()=='post':
res = request.post(url,json=params)
else:
log.error("错误请求method--->",method)
pprint(res)
if __name__ == '__main__':
pytest.main(['-s','test_excel_case.py'])
pycharm小技巧:快捷键——搜索/替换快捷键
1 CTRL + F 查找
2 F3 查找下一个
3 SHIFT + F3 查找上一个
4 CTRL + R 替换
5 CTRL + SHIFT + F 指定路径下查找
6 CTRL + SHIFT + R 指定路径下替换
6、excel参数化运行之运行关联
# -*- coding: utf-8 -*-
# @Time : 2021/12/11 20:07
# @Author : jeffky
# @File : ExcelData.py
from pprint import pprint
from common.ExcelConfig import DataConfig
from utils.ExcelUtil import ExcelReader
class Data:
def __init__(self,testcase_file,sheet_name):
#1、使用excel工具类,获取结果list
# self.reader = ExcelReader("../data/testdata.xlsx", 0)
self.reader = ExcelReader(testcase_file, sheet_name)
# pprint(reader.data())
# 2、列是运行内容,y
def get_run_list(self):
'''
根据是否运行==y,会哦去执行测试用例
:return:
'''
run_list= list()
for line in self.reader.data():
if str(line[DataConfig().is_run]).lower() == "y":
# print(line)
# 3、保存要执行结果,放到新的列表。
run_list.append(line)
# pprint(run_list)
return run_list
def get_case_list(self):
'''
获取全部测试用例
:return:
'''
case_list = [ line for line in self.reader.data()]
return case_list
def get_case_pre(self,pre):
'''
根据前置条件,从全部测试用例获取到测试用例
:param pre:
:return:
'''
#获取全部测试用例
#list判断,执行,获取
run_list =self.get_case_list()
for line in run_list:
if pre in dict(line).values():
return line
return None
# -*- coding: utf-8 -*-
# @Time : 2021/12/10 14:32
# @Author : jeffky
# @File : Base.py
import json
import re
from config.Conf import ConfigYaml
# 1、定义方法init_db
from utils.MysqlUtil import Mysql
p_data= re.compile('\${(.*)}\$')
def init_db(db_alias):
# 2、初始化数据库信息,通过配置文件
db_info = ConfigYaml().get_db_conf_info(db_alias)
host = db_info['db_host']
user = db_info['db_user']
password= db_info['db_password']
database= db_info['db_database']
charset = db_info['db_charset']
port = db_info['db_port']
# 3、初始化mysqkl象
conn =Mysql(host,user,password,database ,charset,port)
return conn
def json_parse(data):
'''
格式化字符转化json格式
:param data:
:return:
'''
# 1、判断headers是否存在,json转义,无需
# if headers:
# header = json.loads((headers))
# else:
# header = headers
return json.loads(data) if data else data
def res_find(data,pattern_data=p_data):
'''
查询
:param data:
:param pattern_data:
:return:
'''
# pattern = re.compile('\${(.*)}\$')
pattern = re.compile(pattern_data)
re_res = pattern.findall(data)
return re_res
def res_sub(data,replace,pattern_data=p_data):
'''
替换
:param data:
:param replace:
:param pattern_data:
:return:
'''
pattern = re.compile(pattern_data)
re_res = pattern.findall(data)
if re_res:
return re.sub(pattern_data,replace,data)
return re_res
def params_find(headers,cookies):
'''
验证请求中是否有${}$需要结果关联
:param headers:
:param cookies:
:return:
'''
if "${" in headers:
headers = res_find(headers)
if "${" in cookies:
cookies = res_find(cookies)
return headers,cookies
if __name__ == '__main__':
print(init_db('db_1'))
# -*- coding: utf-8 -*-
# @Time : 2021/12/12 3:18
# @Author : jeffky
# @File : test_excel_case.py
import json
from pprint import pprint
import pytest as pytest
from common.Base import *
from utils.RequestsUtil import Request
from common import ExcelConfig
from utils.LogUtil import my_log
from config.Conf import ConfigYaml, BASE_DIR
from common.ExcelData import Data
import os
# 1、初始化信息
# 1)初始化测试用例文件
conf_read = ConfigYaml()
case_file =os.path.join((BASE_DIR+os.sep+"data"),conf_read.get_excel_file())
# print(case_file)
# 2)测试用例sheet名称
sheet_name = conf_read.get_excel_sheet()
# 3)获取是否都运行测试用例列表
data_init = Data(case_file,sheet_name)
run_list = data_init.get_run_list()
# 初始化data_conf
data_key = ExcelConfig.DataConfig
# 4)日志
log = my_log()
# 2、测试用例方法,参数化运行
class TestExcel:
# 1、增加pytest
# 2、修改方法参数
# 3、重构函数内容
# 4、pytest.main
def run_api(self,url,method,params=None,header=None,cookie=None):
'''
发送请求api
:return:
'''
request = Request()
if len(str(params).strip()) is not 0:
params=json.loads(params)
# method post/getopt
if str(method).lower()=='get':
# 2、增加headers
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--->",method)
return res
def run_pre(self,pre_case):
url = conf_read.get_conf_url()+pre_case[data_key.url]
print("url---->",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]
# 1、判断headers是否存在,json转义,无需
header =json_parse(headers)
# 3、增加cookis
cookie = json_parse(cookies)
res =self.run_api(url, method, params, header, cookie)
print('前置用例执行条件-----》',res)
return res
# 1)初始化信息,url,data
# 1、增加pytest
@pytest.mark.parametrize("case",run_list)
def test_run(self,case):
# data_key = ExcelConfig.DataConfig
# run_list第1个用例,key获取values
url = conf_read.get_conf_url()+case[data_key.url]
print("url---->",url)
case_id = case[data_key.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]
# 1、验证前置条件
if pre_exec:
# 前置测试用例
pre_case = data_init.get_case_pre(pre_exec)
pre_res = self.run_pre(pre_case)
headers,cookies = self.get_correlation(headers,cookies,pre_res)
# 1、判断headers是否存在,json转义,无需
header =json_parse(headers)
# 3、增加cookis
cookie = json_parse(cookies)
# 2)接口请求
res = self.run_api(url, method, params, header, cookie)
print("测试用例执行----->",res)
# 关联
def get_correlation(self,headers,cookies,pre_res):
# 验证是否有关联
headers_para,cookies_para = params_find(headers,cookies)
# 有关联执行前置用例,获取结果
if len(headers_para):
headers_data = pre_res['body'][headers_para[0]]
# 结果替换
headers = res_sub(headers,headers_data)
if len(cookies_para):
cookies_data = pre_res['body'][cookies_para[0]]
# 结果替换
cookies= res_sub(cookies,cookies_data)
return headers,cookies
if __name__ == '__main__':
pytest.main(['-s','test_excel_case.py'])
#动态关联
# 1、验证前置条件
# 2、找到执行用例
# 3、发送请求,获取前置用例结果
# 发送获取前置测试用例,用例结果
# 数据初始化,get/post,重构
# 4、替换headers变量
# 5、请求发送
7、运行结果验证
修改base
import json
import re
from utils.MysqlUtil import Mysql
from utils.AssertUtil import AssertUtil
from config.Conf import ConfigYaml
from utils.LogUtil import my_log
p_data= re.compile('\${(.*)}\$')
log = my_log()
def assert_db(db_name,result,db_verify):
assert_util = AssertUtil()
# conn = init_db('db_1')
conn = init_db(db_name)
res_db = conn.fetchone(db_verify)
log.debug("数据库查询结果:{}".format(str(res_db)))
# assert_util.assert_body(res['body']['username'],res_db['username'])
# 3、数据库的结果与接口返回的结果验证
# 获取数据库结果的key
verify_list = list(dict(res_db).keys())
# 根据key获取数据库结果,接口结果
for line in verify_list:
# res_line = res['body'][line]
res_line = result[line]
res_db_line = dict(res_db)[line]
# 验证
assert_util.assert_body(res_line, res_db_line)
测试用例
# -*- coding: utf-8 -*-
# @Time : 2021/12/12 3:18
# @Author : jeffky
# @File : test_excel_case.py
import json
from pprint import pprint
import pytest as pytest
from utils.AssertUtil import AssertUtil
from common.Base import *
from utils.RequestsUtil import Request
from common import ExcelConfig
from utils.LogUtil import my_log
from config.Conf import ConfigYaml, BASE_DIR
from common.ExcelData import Data
import os
# 1、初始化信息
# 1)初始化测试用例文件
conf_read = ConfigYaml()
case_file =os.path.join((BASE_DIR+os.sep+"data"),conf_read.get_excel_file())
# print(case_file)
# 2)测试用例sheet名称
sheet_name = conf_read.get_excel_sheet()
# 3)获取是否都运行测试用例列表
data_init = Data(case_file,sheet_name)
run_list = data_init.get_run_list()
# 初始化data_conf
data_key = ExcelConfig.DataConfig
# 4)日志
log = my_log()
# 2、测试用例方法,参数化运行
class TestExcel:
# 1、增加pytest
# 2、修改方法参数
# 3、重构函数内容
# 4、pytest.main
def run_api(self,url,method,params=None,header=None,cookie=None):
'''
发送请求api
:return:
'''
request = Request()
if len(str(params).strip()) is not 0:
params=json.loads(params)
# method post/getopt
if str(method).lower()=='get':
# 2、增加headers
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--->",method)
return res
def run_pre(self,pre_case):
url = conf_read.get_conf_url()+pre_case[data_key.url]
print("url---->",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]
# 1、判断headers是否存在,json转义,无需
header =json_parse(headers)
# 3、增加cookis
cookie = json_parse(cookies)
res =self.run_api(url, method, params, header, cookie)
print('前置用例执行条件-----》',res)
return res
# 1)初始化信息,url,data
# 1、增加pytest
@pytest.mark.parametrize("case",run_list)
def test_run(self,case):
# data_key = ExcelConfig.DataConfig
# run_list第1个用例,key获取values
url = conf_read.get_conf_url()+case[data_key.url]
print("url---->",url)
case_id = case[data_key.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]
# 1、验证前置条件
if pre_exec:
# 前置测试用例
pre_case = data_init.get_case_pre(pre_exec)
pre_res = self.run_pre(pre_case)
headers,cookies = self.get_correlation(headers,cookies,pre_res)
# 1、判断headers是否存在,json转义,无需
header =json_parse(headers)
# 3、增加cookis
cookie = json_parse(cookies)
# 2)接口请求
res = self.run_api(url, method, params, header, cookie)
print("测试用例执行----->",res)
#断言验证
# 状态码, 返回结果内容,数据库相关结果验证
# 状态码
assert_util = AssertUtil()
assert_util.assert_code(int(res['code']),int(code))
# 返回结果内容
assert_util.assert_in_body(str(res['body']),str(expect_result))
# 数据库相关结果验证
# 1、初始化数据库
from common.Base import init_db
# 2、查询sql,excel定义好的
if db_verify:
# conn = init_db('db_1')
# res_db = conn.fetchone(db_verify)
# log.debug("数据库查询结果:{}".format(str(res_db)))
# # assert_util.assert_body(res['body']['username'],res_db['username'])
# # 3、数据库的结果与接口返回的结果验证
# # 获取数据库结果的key
# verify_list = list(dict(res_db).keys())
# # 根据key获取数据库结果,接口结果
# for line in verify_list:
# res_line = res['body'][line]
# res_db_line = dict(res_db)[line]
# # 验证
# assert_util.assert_body(res_line , res_db_line)
assert_db("db_1",res['body'],db_verify)
# 关联
def get_correlation(self,headers,cookies,pre_res):
# 验证是否有关联
headers_para,cookies_para = params_find(headers,cookies)
# 有关联执行前置用例,获取结果
if len(headers_para):
headers_data = pre_res['body'][headers_para[0]]
# 结果替换
headers = res_sub(headers,headers_data)
if len(cookies_para):
cookies_data = pre_res['body'][cookies_para[0]]
# 结果替换
cookies= res_sub(cookies,cookies_data)
return headers,cookies
if __name__ == '__main__':
pytest.main(['-s','test_excel_case.py'])
#动态关联
# 1、验证前置条件
# 2、找到执行用例
# 3、发送请求,获取前置用例结果
# 发送获取前置测试用例,用例结果
# 数据初始化,get/post,重构
# 4、替换headers变量
# 5、请求发送