接口测试平台-78: 多接口之 小用例:返回值提取(路径+正则)+url空显示报错解决

上节设定了两种提取返回值的方式,如图

1. 路径提取法

本节就来实现它,打开run_case.py,找到这空白区域:

如何进行提取和持久化的设计,也以便后续接口进行调用,先按照路径法,提取出来。

注意:因为有些接口返回值并不是json格式字串,而路径法又只能是识别提取json格式。

 

为了方便调试,这里要用一个真实的接口进行测试。大家也可以找找可调通的其他接口做测试。

接口信息如下:

请求方式:get

url:/sugrec?prod=pc_his&from=pc_web&json=1&sid=32812_1464_33049_33059_33099_33101_32962_32846_22160&hisdata=&_t=1606109114553&req=2&csor=0

host:https://www.baidu.co

header:{}

请求结果:{"err_no":0,"errmsg":"","queryid":"0xc5e746e385f8d9"}

这里可以看到 这是一个返回值是json的接口,并且所有人都可以访问。

新建一个大用例和其小步骤,并套用这个接口库的接口:

然后对其的路径法提取设置为:

提取那一串0xc5e...并设计其的对象名为qid,在run_case.py中先试着把这串设置提取出来:

# # 路径提取法
if get_path != '':  # 说明有配置
    print(get_path)

运行下该用例,看看输出:

对其返回值按照这个进行提取:

# 对返回值res进行提取
# # 路径提取法
if get_path != '':  # 说明有配置
    for i in get_path.split('\n'):
        key = i.split('=')[0]
        path = i.split('=')[1]

        py_path = ""
        for j in path.split('/'):
            if j != '':
                if j[0] != '[':
                    py_path += '["%s"]' % j
                else:
                    py_path += j

        print(i)
        print(py_path)
        print('=================================')

这个解析的过程中,对path用/进行分割,然后分别判断每一段,如果不是[开头,那说明是提取的是字典key,否则就是[数字]这样的列表下标。所以一开始设置的空字串py_path 要逐个累加解析过的每一段。

看看效果:

可以看出删掉了/ ,换成了[] 这样就可以直接 在字典后加上,直接提取了:比如字典 :{"a":1} 提取的时候就构造出字符串:{"a":1}["a"] 即可提取到值1。

继续写:

value = eval("%s%s" % (json.loads(res), py_path))
exec('self.%s = value ' % key)

注意看前两句,第一句意思是提取出了这个值,第二句是把这个值给到了一个用户自己设置的变量里。 

 

理论上,遍历完这个循环后,俩个变量qid和en都生成了,打印一下看看对不对。为什么要加self.呢?因为要给他们做成类变量,好方便后续生成的def步骤用例函数调用。(这里后续到底能不能调用成功,先留个悬念,可如果调用不成功,这里还是要改的~)

重启服务,刷新页面,修改断言:

qid=/queryid
en=/err_no

运行效果如下:

看来提取成功了,并且值的类型 还是对的。

 

2. 正则提取法

如法炮制,把正则法提取的代码也写出来。正则就更好办了,因为用户已经为写好了正则语法的左右边界等:

(这里有同学问,这里username后面的单引号是什么意思,其实没意思,就是我们截取的左边界 也就是这个json里,username人家本来后面就带了单引号或双引号。这里解释的不到位,大家可以多加些备注等,正则也可以处理各种格式返回值的提取)

按照实际返回值,写好左右边界,中间要提取的部分用(.*?)代替

z_en=o":(.*?),"e
z_qid=ryid":"(.*?)"

要注意一下,正则提取出来的东西很难确定它的值的类型,因为如果真实返回值是如: "a":"1" 这时候,然后恰好用户又设置成: a":"(.*?)" 这样,那取到的只是1 ,不能擅作主张的把这个1变成整形,因为这个1的确是字符串“1”,而且也可能是使用者不是写错 而是故意要取出来当作整形或者字符串,所以为了避免这种纠纷,暂时规定正则提取出来的全部按照字符串处理~也欢迎大家集思广益,提出更妥善的方案,其中也要考虑我们擅自把1变成整形尚且不表,把abc也变成整形就会报错的情况。

 

具体代码如下:

# # 正则提取法
if get_zz != '':  # 说明有配置
    for i in get_zz.split('\n'):
        key = i.split('=')[0]
        zz = i.split('=')[1]

        value = re.findall(zz, res)[0]
        exec('self.%s = "%s" ' % (key, value))

print(self.z_qid)
print(type(self.z_qid))
print(self.z_en)
print(type(self.z_en))

成功之后,还有些后续问题要处理:

 

3. 路径提取法之去空格

使用者不小心在 =号左右加了空格,这个是pep8语法遵循者常用的写法。设置中=号左右都没空格,但是一不小心,写了一个空格 或者俩个,怎么办呢?

其实只要在代码中 对其提取时,自动删掉空格即可,但不是删掉所有空格,只是key的右侧空格,和path/zz的左侧空格而已:

运用的方法仅仅是在后面加 .rstrip 或者.lstrip,带着空格保存 重启服务 ,运行用例,看看报告:

这次全部打印,可以看到全部打印出来了:

 

4. UI优化

本节内容还差个小尾巴,就是在一开始,可能有的同学注意到,接口库因为接口url太长,导致按钮排版出现问题:

没有对“操作”这栏 的宽度写成了固定的,结果被url这种比例宽度给欺负了的后果,把操作这栏的宽度设置 改成 最小 宽度。

修改P_apis.html

效果如下:

接口名称又被欺负了,那么再给接口名称变成最小宽度:

 

但是这样做之后,显然浏览器又被url给撑破了,连滚动条都出来了。而且页面看着也很乱,这么一大坨url放着。

还有另一个办法,不要让url显示这么长就好了。这个操作在后台进行切割比较易于理解,前端html重新设置宽度比例吧:

找到进入用例库页面的后台函数中控制数据的函数child_json():

每个接口api都新增short_url,值为原始url的?号前面路由的部分,并且最大只要前50个字符串。前端中展示的也不再是api_url了,而是short_url:


这里会遇上url为空的展示500问题,简单解决办法是增加默认值:

不会新增出现url是NoneType的 接口了。线上已存在的接口脏数据怎么处理呢?要么写sql给所有这种接口的url全变成空字符串。要么在split代码加try:

好的,现在可以重启服务,测试下

现在整洁很多,而且没有破坏原始数据:

 

附录:

# 异常值发送请求
@login_required
def error_request(request):
    api_id = request.GET['api_id']
    span_text = request.GET['span_text']
    api = DB_apis.objects.filter(id=api_id)[0]
    method = api.api_method
    url = api.api_url
    host = api.api_host
    headers = api.api_header
    body_method = api.body_method
    new_body = request.GET['new_body']

    # 处理header
    try:
        headers = json.loads(headers)  # 处理header
    except:
        return HttpResponse('请求头不符合json格式!')

    try:
        res_json = {"response": api_send_basic(method, host, url, headers, body_method, new_body), "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')

 

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 深蓝海洋 设计师:CSDN官方博客 返回首页