关键词:httprunner、jsonpath
背景:python3.7.9 + httprunner2.5.7,运行httprunner测试脚本报错。
module 'jsonpath' has no attribute 'jsonpath',没有自己写过jsonpath.py的同名文件。
问题解决步骤:
1、pip3 list查看有jsonpath module
2、修改httprunner框架的response.py文件
- self.parsed_body() --> self.json
- raise exceptions.ExtractFailure --> logger.log_error
def _extract_field_with_jsonpath(self, field):
"""
JSONPath Docs: https://goessner.net/articles/JsonPath/
For example, response body like below:
{
"code": 200,
"data": {
"items": [{
"id": 1,
"name": "Bob"
},
{
"id": 2,
"name": "James"
}
]
},
"message": "success"
}
:param field: Jsonpath expression, e.g. 1)$.code 2) $..items.*.i
:return: A list that extracted from json repsonse example.
"""
#result = jsonpath.jsonpath(self.parsed_body(), field)
result = jsonpath.jsonpath(self.json, field)
if result:
return result
else:
#raise exceptions.ExtractFailure("\tjsonpath {} get nothing\n".
logger.log_error("\tjsonpath {} get nothing\n".format(field))
3、再次运行httprunner的测试脚本,忧伤并没有好一些。
4、再次查看报错「module 'jsonpath' has no attribute 'jsonpath'」,再加度娘指点,于是先确定下调用的jsonpath是哪个。
xxxxdeMacBook-Pro:~ xxxx$ python -c "import jsonpath; print(jsonpath.__file__)"
/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/jsonpath.py
5、知道是调用这个jsonpath.py后,立马查看这个文件,发现有jsonpath属性的。
6、那么,会不会是在调用这个属性的时候失败了呢?于是乎,copy了一个脚本进行调试。
d={
"error_code": 0,
"stu_info": [
{
"id": 2059,
"name": "小白",
"sex": "男",
"age": 28,
"addr": "河南省济源市北海大道32号",
"grade": "天蝎座",
"phone": "18378309272",
"gold": 10896,
"info":{
"card":434345432,
"bank_name":'中国银行'
}
},
{
"id": 2067,
"name": "小黑",
"sex": "男",
"age": 28,
"addr": "河南省济源市北海大道32号",
"grade": "天蝎座",
"phone": "12345678915",
"gold": 100
}
]
}
res= d["stu_info"][1]['name'] #取某个学生姓名的原始方法:通过查找字典中的key以及list方法中的下标索引
print(res) #输出结果是:小黑
import jsonpath
res1=jsonpath.jsonpath(d,'$..name') #嵌套n层也能取到所有学生姓名信息,$表示最外层的{},..表示模糊匹配
print(res1) #输出结果是list:['小白', '小黑']
res2= jsonpath.jsonpath(d,'$..bank_name')
print(res2) #输出结果是list:['中国银行']
res3=jsonpath.jsonpath(d,'$..name123') #当传入不存在的key(name)时,返回False
print(res3) #输出结果是:False
运行结果如下
这下子忧伤是辣么多又辣么大.....
7、不过没关心,可能是版本或依赖包的版本不对导致。再于是乎,和同事对了下python、httprunner以及pip3 list,都是一样的.
8、心拔凉拔凉的,算了,重装下环境吧。噼里啪啦重装了python和httprunner的环境,重启电脑,脚本一运行,嗯,忧伤加倍。
9、和同事请教,同事提出,会不会有重名模块?于是乎
发现有4个jsonpath.py文件。
10、于是把 xxx/site-packages/jsonpath_rw/jsonpath.py重命名为jsonpath-1.py,运行脚本,报错
看来不是这个。于是再把jsonpath-1.py改回jsonpath.py。
11、再把xxx/site-packages/jsonpath_rw/bin/jsonpath.py重命名为jsonpath-1.py。运行脚本,还是报错「module 'jsonpath' has no attribute 'jsonpath'」
12、再次尝试,把/Library/Frameworks/Python.framework/Versions/3.7/bin/jsonpath.py 重命名为 jsonpath-1.py。运行脚本,成功了。
上述是整个问题排查过程,简单梳理下思路就是:
1、错误信息「module 'jsonpath' has no attribute 'jsonpath'」,说明jsonpath模块有安装,但是没有jsonpath模块没有jsonpath属性,所以,有点怀疑是不是jsonpath模块安装有问题,故重新安装。
2、其次应该就是考虑模块重名的问题。但是因为在步骤4查看了jsonpath的调用,于是走入了弯路。
其实没搞明白/Library/Frameworks/Python.framework/Versions/3.7/bin/jsonpath.py是怎么来的?看了下这个文件的内容,确实不对
#!/Library/Frameworks/Python.framework/Versions/3.7/bin/python3.7
# EASY-INSTALL-ENTRY-SCRIPT: 'jsonpath-rw==1.4.0','console_scripts','jsonpath.py'
__requires__ = 'jsonpath-rw==1.4.0'
import re
import sys
from pkg_resources import load_entry_point
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
sys.exit(
load_entry_point('jsonpath-rw==1.4.0', 'console_scripts', 'jsonpath.py')()
)
一直以为调用的是/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/jsonpath.py,没想到实际调用了/Library/Frameworks/Python.framework/Versions/3.7/bin/jsonpath.py。