目录
程序员进行接口测试是确保软件质量和项目成功的关键步骤之一,可以帮助发现接口的缺陷和错误,并及时进行修复,保证接口的正确性和稳定性。
使用 Shell 脚本可以提高接口测试的效率和质量,减少人力成本,提高测试效率和可重复性。
本文以统一下单、支付和支付结果通知为例,介绍几种常见接口使用 Shell 脚本进行测试的情况。
Dubbo 接口
使用 unifiedOrder.sh 进行统一下单:
#!/bin/bash
# 整个测试流程步骤的长度,缺省值为9
steps=${1:-9}
# 测试第一步——下单
step=1
# 取当前时间,结合随机数,简单生成唯一编号
secs=$(date +%s)
seq=$(echo $RANDOM $RANDOM|awk '{printf "%05d%04d",$1,rshift($2,2)}')
outRequestId=${secs}${seq}
orderNo=${secs}${seq}
tim=$(date "+%Y-%m-%d %H:%M:%S")
payment=100
appId=alipayAppId
paymentType=ALIPAY
echo unifiedOrder: outRequestId=$outRequestId orderNo=$orderNo appId=$appId
# 通过telnet命令调用dubbo服务下单接口,<< EOF表示输入在telnet中执行的命令,且多行,最后以EOF结束命令
telnet localhost 20880 << EOF
invoke PayService.unifiedOrder({
"outRequestId": "$outRequestId",
"orderDateTime": "$tim",
"reqDateTime": "$tim",
"orderNo": "$orderNo",
"payment": "$payment",
"productName": "产品名称",
"productDesc": "测试用",
"paymentType": "$paymentType",
"extraParam": "{\"openId\":\"$openId\",\"appId\":\"$appId\"}"
})
EOF
# 测试第二步——支付
let step++
[[ $steps < $step ]] && exit $step;
read -n 1 -sp 'Press any key to pay order. Ctrl + c to abort.'
echo
./payOrder.sh $orderNo
# 测试第三步——支付结果通知
let step++
[[ $steps < $step ]] && exit $step;
read -n 1 -sp 'Press any key to pay notify. Ctrl + c to abort.'
echo
./payNotify.sh $orderNo $payment
HTTP 接口
使用 payOrder.sh 进行订单支付:
#!/bin/bash
orderNo=$1
payChannelCode=ALIPAY
echo payOrder: orderNo=$orderNo payChannelCode=$payChannelCode
# POST方法调用支付接口,参数以json字符串方式,通过-d选项传递
# 使用''可以在json字符串中直接使用"而避免转义\"。但''中不能通过$取变量值,因此将$变量放在''外面
curl -X POST -H 'content-type: application/json' http://localhost:8088/cashier/payOrder -d '{
"orderNo": "'$orderNo'",
"payChannelCode": "ALIPAY"
}'
使用 payNotify.sh 进行支付结果通知:
#!/bin/bash
# 接收传入的参数
outTradeNo=$1
total_amount=$2
# 交易状态,缺省为TRADE_SUCCESS
tradeStatus=${3:-TRADE_SUCCESS}
appId=${4:-xxAppId}
secs=$(date +%s)
seq=$(echo $RANDOM|awk '{printf "%05d",$1}')
notifyId=ntf${secs}${seq}
notify_time=$(date '+%Y%m-%d %H:%M:%S')
echo payNotify: appId=$appId outTradeNo=$outTradeNo tradeStatus=$tradeStatus notifyId=$notifyId
# POST方法调用支付通知接口,参数在url中传递。命令结尾的\表示命令换行
# 选项--data-urlencode表示将它后面的数据进行url编码,该数据会拼接到整个url后面
# 如果有多个参数需要进行url编码,则多次使用--data-urlencode
curl -X POST -G --data-urlencode "notify_time=$notify_time"\
"http://localhost:8077/api/alipay/payNotify?\
notify_id=$notifyId&\
app_id=$appId&\
out_trade_no=$outTradeNo&\
trade_status=$tradeStatus&\
total_amount=$total_amount\
"
Dubbo 3.x 接口
将 Dubbo 升级到 3.x 以后,发现原来的脚本不可以用了!主要表现在两方面:一方面是 telnet 到服务端口没有 invoke 指令,因为这个指令迁到 qos 服务中了。另一方面是指令实现方式的变化,调用接口的参数不允许有空格,因为这会被当成多个参数,导致 invoke 错误:Invalid parameters, format: service.method(args)。
为了保持接口传参的简单格式化,方便维护,对于接口参数仍使用多行文本,在调用接口前将多行文本参数中的注释、空格去掉即可。新建一个脚本,专门实现该处理。该脚本就拿之前一篇文章让SPRING_APPLICATION_JSON的内容允许注释中的脚本稍微修改一下,保存为 unformat.sh 以适应该场景:
#!/bin/bash
str_arr=()
while read -r line; do
if [[ $line =~ ^# ]]; then
continue
fi
str_arr+=($line)
done <<< "$1"
new_str=
for val in "${str_arr[@]}";
do
new_str=$new_str$val
done
echo $new_str|sed 's/ //g'
此脚本最后的 echo 输出处理后的内容,可以作为该脚本的返回值,供其它脚本调用获取。之前适用于 Dubbo 2.x 的 Shell 脚本中,telnet 相关部分做如下修改:
tim=$(date "+%Y-%m-%dT%H:%M:%S")
req=$(cat << EOF
{
"outRequestId": "$outRequestId",
"orderDateTime": "$tim",
"reqDateTime": "$tim",
"orderNo": "$orderNo",
"payment": "$payment",
"productName": "产品名称",
"productDesc": "测试用",
"paymentType": "$paymentType",
"extraParam": "{\"openId\":\"$openId\",\"appId\":\"$appId\"}"
}
EOF
)
req=$(unformat.sh "$req")
telnet localhost 30880 << EOF
invoke PaymentService.unifiedOrder($req)
EOF
注意到第一行,日期时间格式化为字符串时,中间不要使用空格,此处参考 LocalDateTime 的 toString() 方法使用字符'T',与 LocalDateTime 的默认格式化保持一致。多行文本变量值可以使用双引号"",也可以使用单引号''。此处使用req=$(cat << EOF ... EOF) 的方式,是方便参数的编写。如果使用双引号"",参数内容中的""需要转义。如果使用单引号'',参数内容使用 $var 的方式将不会生效。
总结
Shell 脚本可以帮我们做很多事情,并减少重复工作。关于 Shell 的执行环境,MAC 用户可以使用自带终端,WIN 用户可以使用 WSL,让 WSL 使用更方便可以查看专栏另一篇文章。
各位可以根据自己的需要,将上面的脚本稍做修改,就可以用于其它接口的测试。也可以将部分参数改为命令行传入、运行时输入。带来方便的同时,也会让你更喜欢测试,软件质量会更高。