製作一個簡單的命令行測試工具
- 2019 年 11 月 24 日
- 筆記
介面測試時,經常需要對介面發送不同的請求數據,有些介面所需要的參數是靈活多變的,而同一服務可能存在多個不同的介面。按照正常思路,我們需要為每個介面準備一系列的測試集,比如對於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 argparseparser = 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模組來編寫命令行工具的基本方法,關於更多其他高級用法和其他語言下的實現,歡迎大家一起討論交流~


