接口测试平台-51:自动异常测试-5
打开上次没写完的P_apis.html
1. 找到这个error_play函数,已经替换好了请求体,那么接下来就把新请求体和接口id传递给后台即可
在以下俩个位置加上对应传递后台的代码:
$.get('/error_request/', {"api_id": api_id,"new_body": new_body
}, function (ret) {})
2. 添加映射:
urls.py:
url(r'^error_request/$', error_request), # 调用异常测试接口
views.py:
这个函数的功能就是实际发出请求获取请求体,再把请求体返回给前端了。
- 整个代码和调试层传递的类似。但是调试层发送请求的函数的所有接口数据都是从前端获取。
- 而异常值发送请求函数的所有接口数据基本是靠着接口id从数据库获取,然后请求体用前端传过来的新请求体:
代码如下:
# 异常值发送请求
def error_request(request):api_id = request.GET['api_id']new_body = request.GET['new_body']api = DB_apis.objects.filter(id=api_id)[0]method = api.api_methodurl = api.api_urlhost = api.api_hostheader = api.api_headerbody_method = api.body_methodheader = json.loads(header)if host[-1] == '/' and url[0] == '/': # 都有/url = host[:-1] + urlelif host[-1] != '/' and url[0] != '/': # 都没有/url = host+ '/' + urlelse: # 肯定有一个有/url = host + urlif body_method == 'form-data':files = []payload = {}for i in eval(new_body):payload[i[0]] = i[1]response = requests.request(method.upper(), url, headers=header, data=payload, files=files)elif body_method == 'x-www-form-urlencoded':header['Content-Type'] = 'application/x-www-form-urlencoded'payload = {}for i in eval(new_body):payload[i[0]] = i[1]response = requests.request(method.upper(), url, headers=header, data=payload)elif body_method == 'Json':header['Content-Type'] = 'text/plain'response = requests.request(method.upper(), url, headers=header, data=new_body.encode('utf-8'))else:return HttpResponse('非法的请求体类型')# 把返回值传递给前端页面response.encoding = "utf-8"return HttpResponse(response.text)
看看效果(此处效果如果有异常,如3下面部分,补充获取api_id即可):
3. 后端验证:
开始测试:无任何输出;因为api_id没定义,因此抛异常了
重新开始测试:
问题:后台没有成功获取到替换后的请求体,可以理解为,这个传输过程发生了错误或传输成功,但后台解析不了。
原因:请求体中的二维数组无法直接传递,必须变成字符串。
包括常见的json,都是json格式的字符串。只能等到后台接收到之后,再用eval来进行还原成二维数组或字符串了。
所以前端要进行变换(2处):
再测试看看后台输出:
忽略掉这个请求根本没有返回值的报错:(因为url都是随便写,可以之后用自己公司的实际接口测试,但要注意,这个请求频率非常快,接近并发,请不要随意尝试,一瞬间几百个请求出去,服务器可能会报警…)
4. 问题:所有的替换值都变成了字符串?明明要测试的场景里还有整形等。
在js中替换时全当成字符串替换,应替换的是原始用户需求格式,需要对其进行求值再替换,要用变成eval(),有2处
5. 然后开始测试raw-json的格式替换了,代码中加上之前的两处修正,点击开始测试,看看前端console.log的输出如何:
6. 返回值的显示效果
当然现在接口都请求不通,也就没有返回值。那么没返回值的情况怎么办呢?也不能等着服务器后台报错。
所以这里请求加上一个try来捕获,把下面的整个大请求代码段都try了:
前端其实此时已经成功拿到了返回值,虽然返回值现在都是“对不起,接口未通!”,接下来做动态生成html代码,看看最终效果,之后有机会再找个可以请求通的接口来测试。
再次打开P_apis.html
本应该在这两个请求的返回函数中,都写上这段动态生成的代码,但是考虑到代码量应该不少,所以最好是新建一个js函数,专门负责展示。然后在这两个返回函数中调用它即可:
声明了一个error_show_response后,在下面两处进行调用:
进行替换规则这个字符串的构造:
span_text:替换标题,接下来给error_show_response(ret) 加上这个参数
已经拿到了返回体,新建一个多行文本框或者来显示,格式就和最开始的demo一样,demo等写完代码后就删除了。
以上是demo,写完新代码就删了
function error_show_response(span_text,ret) {var error_div = document.getElementById('error_div'); // 声明这个请求体展示窗口var s = document.createElement('span'); //创造替换标题s.innerText = span_text;var t = document.createElement('textarea'); //传教替换内容多行文本t.style = 'width: 99%;height: 50px;border-radius: 5px;color: black;margin-bottom: 10px';t.value = ret;error_div.appendChild(s);error_div.appendChild(t);
}
开始测试,发现结果如下:
7. bug:就是所有的替换标题文案 ,都一样…
在各个位置,打印这些文案,看看究竟出在哪了
现象:最后输出的12次不对,因为2开头的时候,输出的貌似都出了问题
问题:首先奇怪的是,明明12次循环,为啥下面的2开头输出,会在最后位置输出?为啥显示的都是12次循环最后一次的值 b-->中文 ?
原因:js循环的执行顺序是12次循环先执行完,发出去请求就不管了,并不会等到第一次请求返回,再开始第二次循环。
就是12次请求先执行完,过一会,12次请求的返回体才陆续到位,而这时span_text早已被12次请求的最后一次b-->中文赋值了。所以显示的都是这最后一个值。
解决:这里提供几种思路:
- 在变量上下手,防止变量的值被覆盖,每次的变量名都不同
- 锁死循环,必须等待前一次接收到返回体后再开始第二次循环
- 在变量上想办法,做一个变量标题数组,存入所有标题,当调用的时候再依次提取
- 在发出请求的时候,带上这个替换标题,再原封不动的返回
-
比喻:12门火炮, 可以按顺序依次发射。但法预测和决定炮弹落地的顺序。然后要炮弹落地后,根据现场混乱的弹坑,来分辨出都是哪门火炮炸的,这显然很困难。
方案:选择最简单的第四种。让炮弹发射出去的时候,贴上标签。落地后标签掉在弹坑里,自然能分清了。
后台函数:
那么后台之前每次返回基本都是只返回一个字符串,也就是一般只返回一个参数字段。现在要返回的是两个。
- 字符串拼接,然后前端拿到后再给分割开。
- 标准,做一个json串来加入,前端再进行解析即可。
采用标准方法,所以返回代码这么写:
res_json = {"response": response.text, "span_text": span_text}return HttpResponse(json.dumps(res_json), content_type='application/json')except:res_json = {"response": '对不起,接口未通!', "span_text": span_text}return HttpResponse(json.dumps(res_json), content_type='application/json')
然后前端接收到之后,这么解析(2处):
重启服务,刷新页面,开始测试:
发现其实效果已经不错了,没有出现对不上号的情况,把对应的修改,给放入到上面的二维数组中:
看看效果:
发现仍然可以成功。
但是最后仍然留下了一个小问题,显示顺序并不是一开始排好的预期的。
因为各个请求体的返回速度不同,先回来的就先抢到了位置了。不影响实际使用,实际使用中,基本是几百个请求返回体,没人关注摆放顺序,基本就是大致扫一眼,看看没有服务器严重报错的情况就结束测试了。发现有引起服务器报错的,就看一下替换标题记录下来就可以了。
最后别忘了删除那个demo:
8. 上节遗留bug解决:请求体raw-json格式带换行的情况下,打开报错怎么处理
原因:html调用error_test时,按钮的html代码因为换行导致了浏览器解析它失败。
其实严格来说,一般区区一个按钮内的onclick要传这么大量的数据,本就不是一个好办法。万一数据中含有一些引号,双引号,括号,<>等 其实相当于 破坏了html结构,属于一种变异的病毒攻击常用手段。 换行符只是其中一种引起报错的情况,即便解决了换行符,后面也许还会经常互相各种特殊符合引起的html结构错乱的报错。
解决方案:这里最好放弃这么直接传输,可能马上就想到,通过其他拐弯抹角的方式 把这个值传给error_play。
但其实进入页面时给的接口数据,只是给了html。js没有办法直接获得,只能张嘴等html传给它,或者html里用比如input记录下,然后js根据接口id去提取。
所以这里公布俩种解决方案,选用第一种简单方式:
-
每个接口下设置一个隐藏的input。input的id是动态的,内部的value值就存这个接口的请求体(带换行的原封不动的)
-
进入接口库后台函数,不只给html传递接口数据,同时给js传一个接口数据,这样js就可以根据接口id去自己专用的数据中找到接口的请求体了。
先加入隐藏的input :
<input type="text" id="api_error_{{ i.id }}" value="{{ i.api_body }}" />
注意这个input没有隐藏,和放入的位置。看看页面显示效果:
然后给它隐藏:
现在去掉之前旧的传输参数:
给error_test 加入提取api_body的代码:
var api_body = document.getElementById('api_error_' + api_id).value
再来测试下,之前打开报错的带换行情况的接口:
看看效果:
发现已经可以成功打开并且开启异常测试了!