前言:

接口自动化是指模拟程序接口层面的自动化,由于接口不易变更,维护成本更小,所以深受各大公司的喜爱。

第一版入口:接口自动化框架(Pytest+request+Allure)

本次版本做了一些升级,增加了自动生成testcase等,一起来看看吧!~~


一、简单介绍

环境:Mac+Python 3+Pytest+Allure+Request

流程:Charles导出接口数据-自动生成测试用例-修改测试用例-执行测试用例-生成Allure报告

开源: 点击这里,跳转到github

备注⚠️:Charles导出接口应选择文件类型为JSON Session File(.chlsj)

重要模块介绍:

1、writeCase.py :自动读取新的Charles文件,并自动生成测试用例

2、apiMethod.py:封装request方法,可以支持多协议扩展(get\post\put)

3、checkResult.py:封装验证response方法

4、setupMain.py: 核心代码,定义并执行用例集,生成报告


二、目录介绍


三、代码分析

1、测试数据yml(自动生成的yml文件)

# 用例基本信息
test_info:
# 用例标题,在报告中作为一级目录显示
title: blogpost
# 用例ID
id: test_reco_01
# 请求的域名,可写死,也可写成模板关联host配置文件
host: ${host}$
# 请求地址 选填(此处不填,每条用例必填)
address: /api/v2/recomm/blogpost/reco # 前置条件,case之前需关联的接口
premise: # 测试用例
test_case:
- test_name: reco_1
# 第一条case,info可不填
info: reco
# 请求协议
http_type: https
# 请求类型
request_type: POST
# 参数类型
parameter_type: application/json
# 请求地址
address: /api/v2/recomm/blogpost/reco
# 请求头
headers:
# parameter为文件路径时
parameter: reco.json
# 是否需要获取cookie
cookies: False
# 是否为上传文件的接口
file: false
# 超时时间
timeout: 20 # 校验列表 list or dict
# 不校验时 expected_code, expected_request 均可不填
check:
expected_request: result_reco.json
check_type: only_check_status
expected_code: 503 # 关联键
relevance:

2、测试case(自动生成的case.py)

@allure.feature(case_dict["test_info"]["title"])
class TestReco: @pytest.mark.parametrize("case_data", case_dict["test_case"], ids=[])
@allure.story("reco")
@pytest.mark.flaky(reruns=3, reruns_delay=3)
def test_reco(self, case_data):
""" :param case_data: 测试用例
:return:
"""
self.init_relevance = ini_request(case_dict, PATH)
# 发送测试请求
api_send_check(case_data, case_dict, self.init_relevance, PATH)

3、writeCase.py (封装方法:自动生成测试case)

def write_case(_path):
yml_list = write_case_yml(_path)
project_path = str(os.path.abspath('.').split('/bin')[0])
test_path = project_path+'/aff/testcase/'
src = test_path+'Template.py' for case in yml_list:
yml_path = case.split('/')[0]
yml_name = case.split('/')[1]
case_name = 'test_' + yml_name + '.py'
new_case = test_path + yml_path + '/' + case_name
mk_dir(test_path + yml_path)
if case_name in os.listdir(test_path + yml_path):
pass
else:
shutil.copyfile(src, new_case)
with open(new_case, 'r') as fw:
source = fw.readlines()
n = 0
with open(new_case, 'w') as f:
for line in source:
if 'PATH = setupMain.PATH' in line:
line = line.replace("/aff/page/offer", "/aff/page/%s" % yml_path)
f.write(line)
n = n+1
elif 'case_dict = ini_case' in line:
line = line.replace("Template", yml_name)
f.write(line)
n = n + 1
elif 'class TestTemplate' in line:
line = line.replace("TestTemplate", "Test%s" % yml_name.title().replace("_", ""))
f.write(line)
n = n + 1
elif '@allure.story' in line:
line = line.replace("Template", yml_name)
f.write(line)
n = n + 1
elif 'def test_template' in line:
line = line.replace("template", yml_name.lower())
f.write(line)
n = n + 1 else:
f.write(line)
n += 1
for i in range(n, len(source)):
f.write(source[i])

4、apiMethod.py(封装方法:http多协议)

def post(header, address, request_parameter_type, timeout=8, data=None, files=None):
"""
post请求
:param header: 请求头
:param address: 请求地址
:param request_parameter_type: 请求参数格式(form_data,raw)
:param timeout: 超时时间
:param data: 请求参数
:param files: 文件路径
:return:
"""
if 'form_data' in request_parameter_type:
for i in files:
value = files[i]
if '/' in value:
file_parm = i
files[file_parm] = (os.path.basename(value), open(value, 'rb'))
enc = MultipartEncoder(
fields=files,
boundary='--------------' + str(random.randint(1e28, 1e29 - 1))
)
header['Content-Type'] = enc.content_type response = requests.post(url=address, data=enc, headers=header, timeout=timeout)
else:
response = requests.post(url=address, data=data, headers=header, timeout=timeout, files=files)
try:
if response.status_code != 200:
return response.status_code, response.text
else:
return response.status_code, response.json()
except json.decoder.JSONDecodeError:
return response.status_code, ''
except simplejson.errors.JSONDecodeError:
return response.status_code, ''
except Exception as e:
logging.exception('ERROR')
logging.error(e)
raise

5、checkResult.py(封装方法:校验response结果)

def check_result(test_name, case, code, data, _path, relevance=None):
"""
校验测试结果
:param test_name: 测试名称
:param case: 测试用例
:param code: HTTP状态
:param data: 返回的接口json数据
:param relevance: 关联值对象
:param _path: case路径
:return:
"""
# 不校验结果
if case["check_type"] == 'no_check':
with allure.step("不校验结果"):
pass
# json格式校验
elif case["check_type"] == 'json':
expected_request = case["expected_request"]
if isinstance(case["expected_request"], str):
expected_request = readExpectedResult.read_json(test_name, expected_request, _path, relevance)
with allure.step("JSON格式校验"):
allure.attach("期望code", str(case["expected_code"]))
allure.attach('期望data', str(expected_request))
allure.attach("实际code", str(code))
allure.attach('实际data', str(data))
if int(code) == case["expected_code"]:
if not data:
data = "{}"
check_json(expected_request, data)
else:
raise Exception("http状态码错误!\n %s != %s" % (code, case["expected_code"]))
# 只校验状态码
elif case["check_type"] == 'only_check_status':
with allure.step("校验HTTP状态"):
allure.attach("期望code", str(case["expected_code"]))
allure.attach("实际code", str(code))
allure.attach('实际data', str(data))
if int(code) == case["expected_code"]:
pass
else:
raise Exception("http状态码错误!\n %s != %s" % (code, case["expected_code"]))
# 完全校验
elif case["check_type"] == 'entirely_check':
expected_request = case["expected_request"]
if isinstance(case["expected_request"], str):
expected_request = readExpectedResult.read_json(test_name, expected_request, _path, relevance)
with allure.step("完全校验"):
allure.attach("期望code", str(case["expected_code"]))
allure.attach('期望data', str(expected_request))
allure.attach("实际code", str(code))
allure.attach('实际data', str(data))
if int(code) == case["expected_code"]:
result = operator.eq(expected_request, data)
if result:
pass
else:
raise Exception("完全校验失败! %s ! = %s" % (expected_request, data))
else:
raise Exception("http状态码错误!\n %s != %s" % (code, case["expected_code"]))
# 正则校验
elif case["check_type"] == 'Regular_check':
if int(code) == case["expected_code"]:
try:
result = ""
if isinstance(case["expected_request"], list):
for i in case[""]:
result = re.findall(i.replace("\"","\""), str(data))
allure.attach('校验完成结果\n',str(result))
else:
result = re.findall(case["expected_request"].replace("\"", "\'"), str(data))
with allure.step("正则校验"):
allure.attach("期望code", str(case["expected_code"]))
allure.attach('正则表达式', str(case["expected_request"]).replace("\'", "\""))
allure.attach("实际code", str(code))
allure.attach('实际data', str(data))
allure.attach(case["expected_request"].replace("\"", "\'") + '校验完成结果',
str(result).replace("\'", "\""))
if not result:
raise Exception("正则未校验到内容! %s" % case["expected_request"])
except KeyError:
raise Exception("正则校验执行失败! %s\n正则表达式为空时" % case["expected_request"])
else:
raise Exception("http状态码错误!\n %s != %s" % (code, case["expected_code"])) else:
raise Exception("无该校验方式%s" % case["check_type"])

6、setupMain.py(执行用例集,生成测试报告)

def invoke(md):
output, errors = subprocess.Popen(md, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
o = output.decode("utf-8")
return o if __name__ == '__main__':
LogConfig(PATH)
write_case(har_path)
args = ['-s', '-q', '--alluredir', xml_report_path]
pytest.main(args)
cmd = 'allure generate %s -o %s' % (xml_report_path, html_report_path)
invoke(cmd)

7、测试报告


以上,喜欢的话请点赞❤️吧~

欢迎关注我的简书,博客,TesterHome,Github~~~

接口自动化框架2-升级版(Pytest+request+Allure)的更多相关文章

  1. 接口自动化框架(Pytest+request+Allure)

    前言: 接口自动化是指模拟程序接口层面的自动化,由于接口不易变更,维护成本更小,所以深受各大公司的喜爱. 接口自动化包含2个部分,功能性的接口自动化测试和并发接口自动化测试. 本次文章着重介绍第一种, ...

  2. Python+Pytest+Allure+Git+Jenkins接口自动化框架

    Python+Pytest+Allure+Git+Jenkins接口自动化框架 一.接口基础 接口测试是对系统和组件之间的接口进行测试,主要是效验数据的交换,传递和控制管理过程,以及相互逻辑依赖关系. ...

  3. python+request接口自动化框架

    python+request接口自动化框架搭建 1.数据准备2.用python获取Excel文件中测试用例数据3.通过requests测试接口4.根据接口返回的code值和Excel对比 但本章只讲整 ...

  4. python3+request接口自动化框架

    首次书写博客,记录下写的自动化接口框架,框架比较简单,哈哈哈,算是记录下历程把!~~~ 一.本次框架由python3.6 书写 1.准备代码环境,下载python3.6    下载地址:https:/ ...

  5. python+requests接口自动化框架

    为什么要做接口自动化框架 1.业务与配置的分离 2.数据与程序的分离:数据的变更不影响程序 3.有日志功能,实现无人值守 4.自动发送测试报告 5.不懂编程的测试人员也可以进行测试 正常接口测试的流程 ...

  6. 接口自动化框架搭建Unittes+HTMLTestRunner

    本次主要尝试搭建接口自动化框架,基于 unittest+HTMLTestRunner 框架主要模块: config: 存放配置文件 lib: 封装了一些接口前置函数:处理各种事物 log: 存放生成的 ...

  7. 转载:python + requests实现的接口自动化框架详细教程

    转自https://my.oschina.net/u/3041656/blog/820023 摘要: python + requests实现的接口自动化框架详细教程 前段时间由于公司测试方向的转型,由 ...

  8. python + requests实现的接口自动化框架详细教程

    前段时间由于公司测试方向的转型,由原来的web页面功能测试转变成接口测试,之前大多都是手工进行,利用postman和jmeter进行的接口测试,后来,组内有人讲原先web自动化的测试框架移驾成接口的自 ...

  9. Jmeter+ant+Jenkins接口自动化框架搭建

    摘自:https://testerhome.com/topics/13389 一.背景  上一篇讲了Jmeter 接口自动化-脚本数据分离实例,我们知道怎么利用Jmeter去编写接口自动化脚本,但是接 ...

随机推荐

  1. 关于优秀的视频播放器 - PotPlayer

    播放器设置 直接截图: 其他重要功能 1. 切换语音:Alt + A 谢谢浏览!

  2. iptables 【转载】

    一:前言   防火墙,其实说白了讲,就是用于实现Linux下访问控制的功能的,它分为硬件的或者软件的防火墙两种.无论是在哪个网络中,防火墙工作的地方一定是在网络的边缘.而我们的任务就是需要去定义到底防 ...

  3. 《 .NET并发编程实战》实战习题集 - 4 - 如何重用一次性资源

    如何重用以下一次性资源代码呢? string text; using (var stream = new StreamReader(path)) { text = stream.ReadToEnd() ...

  4. winform加快窗体加载速度

    //加快控件加载的速度 protected override CreateParams CreateParams { get { CreateParams cp = base.CreateParams ...

  5. rabbitMQ基础应用

    1.安装erlang [root@localhost ~]#yum -y install erlang 2.安装rabbitMQ [root@localhost ~]#yum -y install r ...

  6. 机甲大师S1机器人编程学习

    机甲大师 S1(RoboMaster S1)是大疆新出的教育机器人,很期待.S1支持Scratch和Python编程.(Scratch是麻省理工学院的“终身幼儿园团队”(Lifelong Kinder ...

  7. 字节流---Day30

    IO概述 当我们在生活中把电脑上的数据拷贝到U盘或者硬盘上时,就是进行数据传输,按照数据的流动方向,我们分为输入(input)和输出(output),即就是所谓IO流 Java中I/O操作主要是指使用 ...

  8. 同一个POD中默认共享哪些名称空间

    如果通过POD的形式来启动多个容器那么它们的名称空间会是共享的么,所以我这里讨论是在默认情况下同一个POD的不同容器的哪些名称空间是打通的.这里先说一下结论,共享的是UTS.IPC.NET.USER. ...

  9. 基于Spring Boot的注解驱动式公众号极速开发框架FastBootWeixin

    本框架基于Spring Boot实现,使用注解完成快速开发,可以快速的完成一个微信公众号,重新定义公众号开发. 在使用本框架前建议对微信公众号开发文档有所了解,不过在不了解公众号文档的情况下使用本框架 ...

  10. 用matlab计算线性回归问题

    看机器学习的时候遇到的第一个算法就是线性回归,高数中很详细的说明了线性回归的原理和最小2乘法的计算过程,很显然不适合手动计算,好在各种语言都有现成的函数使用,让我们愉快的做个调包侠吧 简单线性回归 R ...