Python+request+unittest实现接⼝测试框架集成实例
1、为什么要写代码实现接⼝⾃动化
⼤家知道很多接⼝测试⼯具可以实现对接⼝的测试,如postman、jmeter、fiddler等等,⽽且使⽤⽅便,那么为什么还要写代码实现接⼝⾃动化呢?⼯具虽然⽅便,但也不⾜之处:
测试数据不可控制
接⼝测试本质是对数据的测试,调⽤接⼝,输⼊⼀些数据,随后,接⼝返回⼀些数据。验证接⼝返回数据的正确性。在⽤⼯具运⾏测试⽤例之前不得不⼿动向数据库中插⼊测试数据。这样我们的接⼝测试是不是就没有那么“⾃动化了”。
⽆法测试加密接⼝
这是接⼝测试⼯具的⼀⼤硬伤,如我们前⾯开发的接⼝⽤⼯具测试完全没有问题,但遇到需要对接⼝参数进⾏加密/解密的接⼝,例如 md5、base64、AES 等常见加密⽅式。本书第⼗⼀章会对加密接⼝进⾏介绍。⼜或者接⼝的参数需要使⽤时间戳,也是⼯具很难模拟的。
扩展能⼒不⾜
当我们在享受⼯具所带来的便利的同时,往往也会受制于⼯具所带来的局限。例如,我想将测试结果⽣成 HMTL 格式测试报告,我想将测试报告发送到指定邮箱。我想对接⼝测试做定时任务。我想对接⼝测试做持续集成。这些需求都是⼯具难以实现的。
2、接⼝⾃动化测试设计
接⼝测试调⽤过程可以⽤下图概括,增加了测试数据库
⼀般的接⼝⼯具测试过程:
1、接⼝⼯具调⽤被测系统的接⼝(传参 username="zhangsan")。
2、系统接⼝根据传参(username="zhangsan")向正式数据库中查询数据。
3、将查询结果组装成⼀定格式的数据,并返回给被调⽤者。
4、⼈⼯或通过⼯具的断⾔功能检查接⼝测试的正确性。
接⼝⾃动化测试项⽬,为了使接⼝测试对数据变得可控,测试过程如下:
1、接⼝测试项⽬先向测试数据库中插⼊测试数据(zhangsan 的个⼈信息)。
2、调⽤被测系统接⼝(传参 username="zhangsan")。
3、系统接⼝根据传参(username="zhangsan")向测试数据库中进⾏查询并得到 zhangsan 个⼈信息。
4、将查询结果组装成⼀定格式的数据,并返回给被调⽤者。
5、通过单元测试框架断⾔接⼝返回的数据(zhangsan 的个⼈信息),并⽣成测试报告。
为了使正式数据库的数据不被污染,建议使⽤独⽴的测试数据库。
2、requests库
Requests 使⽤的是 urllib3,因此继承了它的所有特性。Requests ⽀持 HTTP 连接保持和连接池,⽀持使⽤cookie保持会话,⽀持⽂件上传,⽀持⾃动确定响应内容的编码。对request库的更详细的介绍可以看我之前接⼝测试基础的⽂章:
3、接⼝测试代码⽰例
下⾯以之前⽤ python+django 开发的⽤户签到系统为背景,展⽰接⼝测试的代码。
为什么开发接⼝?开发的接⼝主要给谁来⽤?
前端和后端分离是近年来 Web 应⽤开发的⼀个发展趋势。这种模式将带来以下优势:
java语言基础实验总结1、后端可以不⽤必须精通前端技术(HTML/JavaScript/CSS),只专注于数据的处理,对外提供 API 接⼝。
2、前端的专业性越来越⾼,通过 API 接⼝获取数据,从⽽专注于页⾯的设计。
3、前后端分离增加接⼝的应⽤范围,开发的接⼝可以应⽤到 Web 页⾯上,也可以应⽤到移动 APP 上。
在这种开发模式下,接⼝测试⼯作就会变得尤为重要了。
开发实现的接⼝代码⽰例:
# 添加发布会接⼝实现
def add_event(request):
eid = ('eid','') # 发布会id
name = ('name','') # 发布会标题
limit = ('limit','') # 限制⼈数
status = ('status','') # 状态
address = ('address','') # 地址
start_time = ('start_time','') # 发布会时间
if eid =='' or name == '' or limit == '' or address == '' or start_time == '':
return JsonResponse({'status':10021,'message':'parameter error'})
result = Event.objects.filter(id=eid)
if result:
return JsonResponse({'status':10022,'message':'event id already exists'})
result = Event.objects.filter(name=name)
if result:python基础代码实例
flexibility and mobilityreturn JsonResponse({'status':10023,'message':'event name already exists'})
if status == '':
status = 1
try:
ate(id=eid,name=name,limit=limit,address=address,status=int(status),start_time=start_time)
except ValidationError:
error = 'start_time format error. It must be in YYYY-MM-DD HH:MM:SS format.'
return JsonResponse({'status':10024,'message':error})
jfinal版本return JsonResponse({'status':200,'message':'add event success'})
通过POST请求接收发布会参数:发布会id、标题、⼈数、状态、地址和时间等参数。
⾸先,判断eid、name、limit、address、start_time等字段均不能为空,否则JsonResponse()返回相应的状态码和提⽰。JsonResponse()是⼀个⾮常有⽤的⽅法,它可以直接将字典转化成Json格式返回到客户端。
接下来,判断发布会id是否存在,以及发布会名称(name)是否存在;如果存在将返回相应的状态码和提⽰信息。
再接下来,判断发布会状态是否为空,如果为空,将状态设置为1(True)。
最后,将数据插⼊到 Event 表,在插⼊的过程中如果⽇期格式错误,将抛出 ValidationError 异常,接收该异常并返回相应的状态和提⽰,否则,插⼊成功,返回状态码200和“add event success”的提⽰。
# 发布会查询接⼝实现
def get_event_list(request):
eid = ("eid", "") # 发布会id
name = ("name", "") # 发布会名称
if eid == '' and name == '':
return JsonResponse({'status':10021,'message':'parameter error'})
if eid != '':
event = {}
try:
result = (id=eid)
except ObjectDoesNotExist:
return JsonResponse({'status':10022, 'message':'query result is empty'})
else:
event['eid'] = result.id
event['name'] = result.name
event['limit'] = result.limit
event['status'] = result.status
event['address'] = result.address
event['start_time'] = result.start_time
return JsonResponse({'status':200, 'message':'success', 'data':event})
if name != '':
源码资本曹毅如何投资今日头条datas = []
results = Event.objects.filter(name__contains=name)
if results:
for r in results:
event = {}
event['eid'] = r.id
event['name'] = r.name
event['limit'] = r.limit
event['status'] = r.status
event['address'] = r.address
event['start_time'] = r.start_time
datas.append(event)
return JsonResponse({'status':200, 'message':'success', 'data':datas})
else:
return JsonResponse({'status':10022, 'message':'query result is empty'})
通过GET请求接收发布会id和name 参数。两个参数都是可选的。⾸先,判断当两个参数同时为空,接⼝返回状态码10021,参数错误。
如果发布会id不为空,优先通过id查询,因为id的唯⼀性,所以,查询结果只会有⼀条,将查询结果以 key:value 对的⽅式存放到定义的event字典中,并将数据字典作为整个返回字典中data对应的值返回。
name查询为模糊查询,查询数据可能会有多条,返回的数据稍显复杂;⾸先将查询的每⼀条数据放到⼀个字典event中,再把每⼀个字典再放到数组datas中,最后再将整个数组做为返回字典中data对应的值返回。
接⼝测试代码⽰例
#查询发布会接⼝测试代码
import requests
url = "127.0.0.1:8000/api/get_event_list/"
r = (url, params={'eid':'1'})
result = r.json()
print(result)
assert result['status'] == 200
assert result['message'] == "success"
assert result['data']['name'] == "xx 产品发布会"
assert result['data']['address'] == "北京林匹克公园⽔⽴⽅"
assert result['data']['start_time'] == "2016-10-15T18:00:00"
unicode码表下载因为“发布会查询接⼝”是GET类型,所以,通过requests库的get()⽅法调⽤,第⼀个参数为调⽤接⼝的URL地址,params设置接⼝的参数,参数以字典形式组织。
json()⽅法可以将接⼝返回的json格式的数据转化为字典。
接下来就是通过 assert 语句对接字典中的数据进⾏断⾔。分别断⾔status、message 和data的相关数据等。
使⽤unittest单元测试框架开发接⼝测试⽤例
#发布会查询接⼝测试代码
import unittest
import requests
class GetEventListTest(unittest.TestCase):
def setUp(self):
self.base_url = "127.0.0.1:8000/api/get_event_list/"
def test_get_event_list_eid_null(self):
''' eid 参数为空 '''
r = (self.base_url, params={'eid':''})
result = r.json()
self.assertEqual(result['status'], 10021)
self.assertEqual(result['message'], 'parameter error')
def test_get_event_list_eid_error(self):
''' eid=901 查询结果为空 '''
r = (self.base_url, params={'eid':901})
result = r.json()
self.assertEqual(result['status'], 10022)
self.assertEqual(result['message'], 'query result is empty')
def test_get_event_list_eid_success(self):
''' 根据 eid 查询结果成功 '''
r = (self.base_url, params={'eid':1})
result = r.json()
self.assertEqual(result['status'], 200)
self.assertEqual(result['message'], 'success')
self.assertEqual(result['data']['name'],u'mx6发布会')
self.assertEqual(result['data']['address'],u'北京国家会议中⼼')
def test_get_event_list_nam_result_null(self):
''' 关键字‘abc'查询 '''
r = (self.base_url, params={'name':'abc'})
result = r.json()
self.assertEqual(result['status'], 10022)
self.assertEqual(result['message'], 'query result is empty')
def test_get_event_list_name_find(self):
''' 关键字‘发布会'模糊查询 '''
r = (self.base_url, params={'name':'发布会'})
result = r.json()
self.assertEqual(result['status'], 200)
self.assertEqual(result['message'], 'success')
self.assertEqual(result['data'][0]['name'],u'mx6发布会')
self.assertEqual(result['data'][0]['address'],u'北京国家会议中⼼')
49if __name__ == '__main__':
unittest.main()
unittest单元测试框架可以帮助组织和运⾏接⼝测试⽤例。
4、接⼝⾃动化测试框架实现
关于接⼝⾃动化测试,unittest 已经帮我们做了⼤部分⼯作,接下来只需要集成数据库操作,以及 HTMLTestRunner测试报告⽣成扩展即可。
框架结构如下图:
pyrequests 框架:
db_fixture/:初始化接⼝测试数据。
interface/:⽤于编写接⼝⾃动化测试⽤例。
report/:⽣成接⼝⾃动化测试报告。
db_config.ini :数据库配置⽂件。
HTMLTestRunner.py unittest 单元测试框架扩展,⽣成 HTML 格式的测试报告。
run_tests.py :执⾏所有接⼝测试⽤例。
4.1、数据库配置
⾸先,需要修改被测系统将数据库指向测试数据库。以 MySQL数据库为例,针对 django 项⽬⽽⾔,修改.../guest/settings.py ⽂件。可以在系统测试环境单独创建⼀个测试库。这样做的⽬的是让接⼝测试的数据不会清空或污染到功能测试库的数据。其他框架开发的项⽬与django项⽬类似,这个⼯作⼀般由开发同学完成,我们测试同学更多关注的是测试框架的代码。
4.2、框架代码实现
4.2.1、⾸先,创建数据库配置⽂件.../db_config.ini
4.2.2、接下来,简单封装数据库操作,数据库表数据的插⼊和清除,.../db_fixture/ mysql_db.py
import pymysql.cursors
import os
import configparser as cparser
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论