Package: testtp
Testtphttp client for testersSupported Featuresdefaultdata 系统级及接口级的默认参数Session级默认参数API级默认参数render 参数动态渲染（变量或者函数）数据变量函数变量validate 基于模板的数据校验response校验预处理后校验Built withrequestsjmespathschemaloguruInstallationpython -m pip install testtp默认参数Session级默认参数Session继承自requests.Session.利用requests.Session实现默认数据。fromtesttpimportSessions=Session()s.headers['X-request-type']='autotest's.params={'default_params':'value'}s.get('http://httpbin.org/get',params={'custom':'query'},headers={'X-token':'loda'})>>>OUTPUT2020-12-0519:26:03.677|SEND|testtp.Req:_restore_resp:22-<=requesturl=>http://httpbin.org/get?default_params=value&custom=query2020-12-0519:26:03.682|RECV|testtp.Req:_restore_resp:23-<=responsedata=>{"args":{"custom":"query",# 本次请求中的params"default_params":"value"# Session中所有请求的默认params},"headers":{"Accept":"*/*","Accept-Encoding":"gzip, deflate","Host":"httpbin.org","User-Agent":"python-requests/2.25.0","X-Amzn-Trace-Id":"Root=1-5fcb6e4c-1d48a5716e5a0a1b2328d089","X-Request-Type":"autotest",# Session中所有请求默认header"X-Token":"loda"# 本次请求中的header},"origin":"159.138.88.145","url":"http://httpbin.org/get?default_params=value&custom=query"}API级别默认参数使用defaultdata装饰器实现添加接口默认参数classClient(Session):def__init__(self,host):self.host=hostsuper().__init__()# 定义api接口，添加默认header和body数据@defaultdata(headers={"X-API-header":"default-API"},json={"default-body-data":"some_api"})defsome_api(self,**kwargs):self.post(self.host+'/post',**kwargs)c=Client('http://httpbin.org')c.some_api(json={'real':'hadogen'})>>>OUTPUT2020-12-0621:44:47.948|SEND|testtp.Req:_wrapper:35-<=requestbody=>{"default-body-data":"some_api",# API默认参数"real":"hadogen"# 本次请求参数}2020-12-0621:44:48.432|SEND|testtp.Req:_restore_resp:22-<=requesturl=>http://httpbin.org/post2020-12-0621:44:48.438|RECV|testtp.Req:_restore_resp:23-<=responsedata=>{"args":{},"data":"{\"default-body-data\":\"some_api\",\"real\":\"hadogen\"}","files":{},"form":{},"headers":{"Accept":"*/*","Accept-Encoding":"gzip, deflate","Content-Length":"52","Content-Type":"application/json","Host":"httpbin.org","User-Agent":"python-requests/2.25.0","X-Amzn-Trace-Id":"Root=1-5fcce04f-26e703c65519aff126e74acf","X-Api-Header":"default-API"#API-默认参数},"json":{"default-body-data":"some_api",# API默认参数"real":"hadogen"# 本次请求参数},"origin":"61.149.134.32","url":"http://httpbin.org/post"}数据动态渲染使用预定义的规则标识数据中的变量，执行时会将testdata对应位置的值做替换*用字符串规则来标识函数和变量，使得测试数据为json格式，方便数据的存储于外部文件或数据库变量缓存---cache“{{ x }}"字符串括起来的数据x被认为是变量，运行时将替换成cache中的对应数据。s=Session()s.cache={'token_holder':'real_token'}# 设置缓存数据body={'data':'testdata','token':'{{ token_holder }}'}s.post('http://httpbin.org/post',json=body)>>>OUTPUT2020-12-0622:07:40.964|SEND|testtp.Req:_wrapper:35-<=requestbody=>{"data":"testdata","token":"real_token"# token被替换成cache中的数据}上下文数据缓存---stashSession将最近一次请求的response存储。使用stash函数可以从response数据抽取关键的数据，存储到cache，供后面请求使用,
json_query提取规则为jmespath规则s=Session()s.cache={'token_holder':'real_token'}body={'data':'testdata','token':'{{ token_holder }}'}s.post('http://httpbin.org/post',json=body)s.stash(json_query='headers.Host',key='host')# 将返回的content中 'header.Host'字段存到缓存cache中，key为'host'print(self.cache)>>>OUTPUT{"token_holder":"real_token","host":"httpbin.org"}body={'context_vars':'{{ host }}'}s.post('http://httpbin.org/post',json=body)>>>OUTPUT2020-12-0622:07:41.644|SENDxx|testtp.Req:_wrapper:35-<=requestbody=>{"context_vars":"httpbin.org"}使用函数实时计算参数---register_render“{% f(x) %}"字符串括起来的数据f(x)被认为是函数，运行时将执行函数来生成数据。支持python内置函数例如random.randint()， 也可以用register_render将自定义函数注册给渲染器使用。defget_timestamp(shift:int):returnint(time.time())+shifts=Session()s.register_render(get_timestamp)body={'data':'testdata','timestamp':'{% get_timestamp(100) %}'}s.post('http://httpbin.org/post',json=body)>>>OUTPUT2020-12-0622:36:32.784|SEND|testtp.Req:_wrapper:35-<=requestbody=>{"data":"testdata","timestamp":1607265492# 实际参数为get_timestamp函数返回的当前时间戳}数据校验校验返回body---validatevalidate方法对response进行格式校验， scm与请求数据一样会经过render处理，支持变量和函数规则同"{{ x }}", "{% f %}".*注意schema中的函数只传函数名，执行时会将response对应位置的值作为参数调用f，函数f的返回，应是一个bool值。defis_url(s):returns.startswith('http')s=Session()s.get('http://httpbin.org/get')scm={"args":{},"headers":{"Accept":"{% str %}","Accept-Encoding":"{% str %}","Host":"httpbin.org","User-Agent":"{% str %}","X-Amzn-Trace-Id":"{% str %}"},"origin":"{% str %}","url":"http://httpbin.org/get"}s.validate(scm)>>>OUTPUT2020-12-0714:40:05.689|SEND|testtp.Req:_restore_resp:22-<=requesturl=>http://httpbin.org/get2020-12-0714:40:05.691|RECV|testtp.Req:_restore_resp:23-<=responsedata=>{"args":{},"headers":{"Accept":"*/*","Accept-Encoding":"gzip, deflate","Host":"httpbin.org","User-Agent":"python-requests/2.25.0","X-Amzn-Trace-Id":"Root=1-5fcdce45-6e7808ba224497484deb1bf1"},"origin":"223.223.188.146","url":"http://httpbin.org/get"}2020-12-0714:40:05.695|DEBUG|testtp.Req:validate:81-<=schematemplate=>{'args':{},'headers':{'Accept':<class'str'>, 'Accept-Encoding': <class 'str'>, 'Host': 'httpbin.org', 'User-Agent': <class 'str'>, 'X-Amzn-Trace-Id': <class 'str'>}, 'origin': <class'str'>,'url':<functiontest_validate_response_custom_function.<locals>.is_urlat0x000001B478983280>}数据抽取---json_query有些场景下需要对返回数据进行一些预处理（如：抽取关键字段，求和，求最大值等），之后才进行校验，这时需要传入数据处理规则json_query,提取规则为jmespath规则data={'data_list':[{'type':'A','count':80},{'type':'B','count':90},{'type':'C','count':70},{'type':'D','count':50},]}url='http://httpbin.org/post's=Session()s.post(url,json=data)scm=['A','B','C','D']s.validate(schema=scm,json_query='json.data_list[].type')>>>OUTPUT2020-12-0714:38:31.241|RECV|testtp.Req:_restore_resp:23-<=responsedata=>{"args":{},"data":"{\"data_list\": [{\"type\":\"A\",\"count\": 80}, {\"type\":\"B\",\"count\": 80}, {\"type\":\"C\",\"count\": 80}, {\"type\":\"D\",\"count\": 80}]}","files":{},"form":{},"headers":{"Accept":"*/*","Accept-Encoding":"gzip, deflate","Content-Length":"127","Content-Type":"application/json","Host":"httpbin.org","User-Agent":"python-requests/2.25.0","X-Amzn-Trace-Id":"Root=1-5fcdcde7-332bb4ee193f31915faee06b"},"json":{"data_list":[{"count":80,"type":"A"},{"count":90,"type":"B"},{"count":70,"type":"C"},{"count":50,"type":"D"},]},"origin":"223.223.188.146","url":"http://httpbin.org/post"}2020-12-0714:38:31.246|DEBUG|testtp.Req:validate:73-<=jsonquery=>json.data_list[].type2020-12-0714:38:31.247|DEBUG|testtp.Req:validate:74-<=extractbody=>['A','B','C','D']2020-12-0714:38:31.248|DEBUG|testtp.Req:validate:81-<=schematemplate=>['A','B','C','D']