re json提取_httprunner如何提取数据串联上下游接口

本文介绍了如何在HttpRunner中从上游接口响应中提取参数,并传递给下游接口。讲解了HttpRunner的源码分析过程,特别是关于数据提取的关键函数,如`extract_field`和`query_json`,强调了通过`sub_query`来获取字典中的最后一个值。此外,还鼓励读者查看开源框架源码以提升自身技能。
摘要由CSDN通过智能技术生成
a2f858162482813f0d06b69f78cfd790.png

189ab197a88c0a46b13f8f2c250847dc.png

httprunner进行接口测试时,从上一个接口提取参数传递给下游接口,如何获取数据里最后一个值?

afae452a2d5aee1f875eb6baa26beb1f.png

突然被学员问道一个httprunner的问题,惭愧的是大猫之前没有是通过httprunner,又不好意思说不会,只能硬着头皮去看源码了。

3b6e96f8865931e907ad07b044b998f2.png

问题其实很简单,怎么处理我不管,反正你得给答案。看一眼同学反馈的截图,确实不难,问题很简单。请求某一个接口,接口返回的content里包含多个字段,需要获取到最后一个字典里的数据。是不是觉得很简单?

75dd1fa1646c616254db1b3524093bdf.png

对于这么具体的问题,大猫当然是第一反应去百度啦!当然,如果能简单百度到答案,学员也不会来问我,因此,结果可想而知,百度没有标准答案!

26b6e2a644829ea03971e030b7611ec9.png

不过百度一点用处也没有么,也不尽然,至少对于一只从来没有使用过httprunner的大猫来说,知道从响应提取数据使用extract关键字。

既然百度没有标准答案,我们就代码里找,大猫最不怕的就是看代码,大江大浪都走过来了,还能这几千行代码里翻船?

看代码先要去github把代码拉取到本地(这里就不写怎么做了),用pycharm打开,然后使用pycharm的“find in path...”进行全局查找,像这样:

6e20386609d5642be6643e89479e298f.png

6ec2d5526af38183172f87732b8eae25.png

我们点击去看下代码的实现细节,没准可以发现蛛丝马迹。

if not extractors:return {}logger.log_debug("start to extract from response object.")extracted_variables_mapping = OrderedDict()extract_binds_order_dict = utils.ensure_mapping_format(extractors)for key, field in extract_binds_order_dict.items(): extracted_variables_mapping[key] = self.extract_field(field)return extracted_variables_mapping

代码实现相当简洁,实例化一个OrderedDict用于存储提取后的数据,采用extract_field函数来执行具体的提取数据操作。我们接着看extract_field函数。

text_extractor_regexp_compile = re.compile(r".*\(.*\).*")

if text_extractor_regexp_compile.match(field):value = self._extract_field_with_regex(field)else:value = self._extract_field_with_delimiter(field)

extract_field的核心逻辑也非常简洁,采用re.compile判断表达式是否为正则,是的话执行正则表达式提取_extract_field_with_regex,如果不是正则采用分隔符提取方式,_extract_field_with_delimiter,我们需要的是分隔符方式提取,因此看_extract_field_with_delimiter函数的实现。

_extract_field_with_delimiter函数实现略微复杂,函数里对查询字符串进行了分级处理,content.person.name.first_name被分成top_query:content和sub_query:[person, name, first_name]。

同时不同的top_query有不同的处理方法,例如top_query若是status_code,encoding,ok,reason,url等则不能有sub_query,否则会抛出异常(这里和响应对象结构有关系);

if top_query in ["status_code", "encoding", "ok", "reason", "url"]:if sub_query:# status_code.XXerr_msg = u"Failed to extract: {}\n".format(field) logger.log_error(err_msg)raise exceptions.ParamsError(err_msg)return getattr(self, top_query)

对于top_query是cookies和headers的处理,若存在sub_query则以sub_query为key进行取值,否则返回cookie或header整体。

elif top_query == "cookies": cookies = self.cookiesif not sub_query:# extract cookiesreturn cookiestry:return cookies[sub_query]except KeyError: err_msg = u"Failed to extract cookie! => {}\n".format(field) err_msg += u"response cookies: {}\n".format(cookies) logger.log_error(err_msg)raise exceptions.ExtractFailure(err_msg)

如果top_query是content,text或json则使用query_json函数进一步处理。当然,处理前进行了一次判断,sub_query是字典、列表还是数字。

elif top_query in ["content", "text", "json"]:try: body = self.jsonexcept exceptions.JSONDecodeError: body = self.textif not sub_query:# extract response bodyreturn bodyif isinstance(body, (dict, list)):# content = {"xxx": 123}, content.xxxreturn utils.query_json(body, sub_query)elif sub_query.isdigit():# content = "abcdefg", content.3 => dreturn utils.query_json(body, sub_query)else:# content = "abcdefg", content.xxxerr_msg = u"Failed to extract attribute from response body! => {}\n".format(field) err_msg += u"response body: {}\n".format(body) logger.log_error(err_msg)raise exceptions.ExtractFailure(err_msg)

query_json函数是实现取值的关键,函数使用分隔符讲sub_query切分成字符串数据,采用循环遍历数据。

for key in query.split(delimiter):if isinstance(json_content, (list, basestring)): json_content = json_content[int(key)]    elif isinstance(json_content, dict): json_content = json_content[key]else: logger.log_error("invalid type value: {}({})".format(json_content, type(json_content))) raise_flag = True

这里如果数据是列表则将key转化为数字取值,否则认为是字典直接用key取值。既然代码是转化成整形,整数有正整数,负整数和零,理论上提取数据的字符串可以有content.person.-1.name.first_name

这样的存在。这里可以理解为从content里取最后一个person的name的first_name。

b08890210891eb03aec50a17a0fb25a4.pngea9b8d5ab7ad8eeb5511a057f7e9e59a.png另外,这里多说一句,可以看见httprunner的代码并不难python测开的学员应该都能看到懂,希望大家多看看开源框架的代码,提升自己的代码能力,也希望大家报名我的课程。

e27201e0a2469c9a9a7be7bf1ef218d4.gif

Bye~

RECOMMEND

testfan一直致力于提高整个测试行业技术实力,近期特推出”大咖解题--公益提升计划“项目,帮助所有测试从业者走上高端测试之路!

f470967e1c6dc24ca5080a7bdb87c473.png

点击文章底部的阅读原文:

可报名参加本期解题--7月21日晚上9点“如何做合格的性能测试工程师

扫上图加安然老师微信可解锁上期解题视频,暗号:“接口测试框架设计

d39bdff3bd957af968ceaf1b09d84ebe.png

da79324450c1cd089b18a9d05dfbd189.gif

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值