接口测试时,经常需要对接口发送不同的请求数据,有些接口所需要的参数是灵活多变的,而同一服务可能存在多个不同的接口。按照正常思路,我们需要为每个接口准备一系列的测试集,比如对于http接口的post请求,我们可能要准备不同的json。在json中,如果测试时只需要字段值(value)的变化,可以结合像jmeter这种测试工具的参数化功能来完成,实现起来还比较简单方便。而很多时候,不只是value,连key也要根据需求来改变,有时要传,有时不要传。这种情况下,再通过参数化方法来解决就会变得很不方便,即使可以实现,但准备测试集也要花费不少时间。
遇到这种相对“复杂”的情况,我们不妨换一种思路。平时用到的测试工具有一类是命令行工具,这种工具对于参数的设置就非常灵活。如果能将某个请求或某些请求封装在一个命令行工具中,使用的时候传入一些命令行参数来实现各种不同的请求,可以大大简化参数设置的难度,有效提升测试效率。同时,像grpc接口这种不方便用postman、jmeter等工具来直接测试的接口,也可以通过编写简易的命令行工具来进行测试。下面就简单介绍下这种工具的制作方法及实际应用的场景。
一、命令行工具的编写
各种语言下都有相应的方法实现命令行工具的编写,本文主要以python为例,用到的模块为argparse。
一般的使用流程:
1、引入argparse模块 import argparse
2、创建一个解析对象(parser)
3、向该对象中添加你要关注的命令行参数和选项(parser.add_argument)
4、进行解析(parser.parse_args())
下面是使用argparse模块的一个简单例子
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("printstring")
parser.add_argument("--printnumber")
args = parser.parse_args()
print (args.printstring)
print (args.printnumber)
将上述代码保存为test.py
运行结果:
由此可见,命令行参数分为两种,一种是不带前缀(--)的位置参数,另一种是带前缀(--)的可选参数。位置参数传参时无需指定参数名,但必传,不传会报错;可选参数传参时必须注明参数名,但可以选择不传(不考虑required属性的情况下)。同时,传参的顺序可以调换,不影响解析。
除了上述这种基本用法外,argparse模块还有很多其他的用法,在此不一一介绍,有兴趣的朋友可以自行了解。下面来根据一个实际中的应用,具体说说argparse模块编写命令行工具如何与接口测试相结合。
二、在接口测试中的应用
在一个关于语音识别http接口的测试中,需要用post方式以json形式传递用来识别的音频文件链接和相关参数。其中参数部分除了固定的字段外,有很多是可选内容,用来开启一些额外的功能(excfgs字段)。例如:
"excfgs":{ "@type": "type.googleapis.com/sogou.spc.asr.v1.LongrunningFuncA", "FuncA": string},{ "@type": "type.googleapis.com/sogou.spc.asr.v1.LongrunningFuncB", "FuncB": string
},{ "@type": "type.googleapis.com/sogou.spc.asr.v1.LongrunningFuncC", "FuncC": string "name": "audio_ch_count", "value": { "@type": "type.googleapis.com/google.protobuf.Field", "number": 2}...}
其中FuncA, FuncB, FuncC等等这些功能都是选择开启的,需要在传参时设置,而开启某个功能不是仅仅设置单个字段值,而是需要额外添加多个字段,并且根据实际情况进行对参数值进行设置。对于这种情况,一般我们可能要准备多个json以便测试,而且修改参数十分麻烦,更不利于自动化测试。这时,可以尝试编写命令行工具来简化传参难度(本文代码中的接口字段名均为假名,只为说明需要)。
首先,在命令行工具的代码中添加所需的参数(将代码保存为cmdasr.py):
import argparseimport longrunning_recognize
def subcmd_longrunning_recognize(args): longrunning_recognize.run(args)
parser = argparse.ArgumentParser()subparsers = parser.add_subparsers(help='sub-command help')
subparser_lrr = subparsers.add_parser('recognize', help='invoking asr-longrunning-recognize service')subparser_lrr.set_defaults(func=subcmd_longrunning_recognize)
#define args of asr-longrunning-recognizegroup_lrr=subparser_lrr.add_argument_group('args of asr-longrunning-recognize')group_lrr.add_argument('--FuncA', help="enable FuncA and set value",default='')group_lrr.add_argument('--FuncB', help="enable FuncB and set value",default='')group_lrr.add_argument('--FuncC', help="enable FuncC and set value",default='')group_lrr.add_argument('--FuncC-number', help="set FuncC number",default=2,type=int)
args=parser.parse_args()args.func(args)
这里用到的子命令和参数组,可以更好地整合代码,简化使用,减少工作量。
在命令行部分编写完成后,就可以将其应用到请求的部分了。在请求实现的代码中,我们可以根据命令行传入的参数,来决定是否添加相应功能字段和具体的参数值。
class LongrunningRecognize: def __init__(self,args): url="http://test.spc.sogou/apis/asr/v/longrunning_recognize" data={ config:{ """ 一些固定参数 """ "extcfgs":[] }, "audio": { "uri": "audioURL" } } if args.FuncA!='': data['config']['extCfgs'].append({ "@type": "type.googleapis.com/sogou.spc.asr.v1.LongrunningFuncA", "FuncA": args.FuncA }) if args.FuncB!='': data['config']['extCfgs'].append({ "@type": "type.googleapis.com/sogou.spc.asr.v1.LongrunningFuncB", "FuncB": args.FuncB }) if args.FuncC!='': data['config']['extCfgs'].append({ "@type": "type.googleapis.com/sogou.spc.asr.v1.LongrunningFuncC", "FuncC": args.FuncC "name": "audio_ch_count", "value": { "@type": "type.googleapis.com/google.protobuf.Field", "number": args.FuncC_number }) headers={ "aid": "111222333" } res=requests.post(url=url,headers=headers,data=json.dumps(data).encode("UTF-8")) ret=res.text
如此设置后,我们就可以通过命令行参数来启动对应的功能,使用起来十分灵活、简便:
python cmdasr.py recognize --FuncA="hello" --FuncB="world" --FuncC="haha" --FuncC-number=1
后续还可以通过pyinstaller将源码编译成可执行文件,应用到jmeter等多线程接口自动化测试工具之中,实现自动化的性能、压力、稳定性测试。
三、总结
本期为大家介绍了通过编写命令行工具来实现简化接口传参以方便测试的有关内容。这种方法适用于大部分的接口测试,除了简化传参,还可以应用于grpc接口测试,实用性较强。本文只简单介绍了python下使用argparse模块来编写命令行工具的基本方法,关于更多其他高级用法和其他语言下的实现,欢迎大家一起讨论交流~