SHELL自动化--接口测试
#!/bin/bash
fileNum=`ls /bin/testShell/apiCheck_shell/logs/ | grep $(date "+%Y-%m-%d") | wc -w`
day=$(date "+%Y-%m-%d")-${fileNum}
# 设置并发的进程数
thread_num=`cat /bin/testShell/apiCheck_shell/check.conf | grep thread_num`
thread_num=${thread_num#*thread_num=}
apiNum=0
annotationNum=0
passNum=0
failNum=0
failList="\n"
echo "" > /bin/testShell/apiCheck_shell/logs/apiCheck_err.log
echo "" > /bin/testShell/apiCheck_shell/logs/result.log
TMPFIFO=/tmp/$$.fifo  #声明管道名称,'$$'表示脚本当前运行的进程PID
mkfifo $TMPFIFO       #创建管道
exec 6<>${TMPFIFO}    #创建文件标示符“6”,这个数字可以为除“0”、“1”、“2”之外的所有未声明过的字符,以读写模式操作管道文件;系统调用exec是以新的进程去代替原来的进程,但进程的PID保持不变,换句话说就是在调用进程内部执行一个可执行文件
rm -rf ${TMPFIFO}     #清除创建的管道文件
# 为文件描述符创建占位信息
for ((i=1;i<=${thread_num};i++))
do
{
#借用read命令一次读取一行的特性,使用一个echo默认输出一个换行符,来确保每一行只有一个线程占位;这里让人联想到生产者&消费者模型,管道文件充当消息队列,来记录消费者的需求,然后由生产者去领任务,并完成任务,这里运用了异步解耦的思想
    echo
}
done >&6 # 事实上就是在fd6中放置了$thread_num个回车符
#发送请求并记录请求返回值
send()
{
	echo "$(date "+%Y-%m-%d %H:%M:%S"):============================================================================================================================" >> /bin/testShell/apiCheck_shell/logs/apiCheck${day}.log
	max_time=`cat /bin/testShell/apiCheck_shell/project/${project}/server.conf | grep max_time:`
	max_time=${max_time#*max_time:}
	ContentType=`cat /bin/testShell/apiCheck_shell/project/${project}/server.conf | grep ContentType:`
        ContentType=${ContentType#*ContentType:}
	if [[ "${project}" == "TEST-1" ]] || [[ "${project}" == "TEST-2" ]]
	then
        	echo "$(date "+%Y-%m-%d %H:%M:%S"):  curl --connect-timeout ${max_time} -m ${max_time} -s -i -X POST --cookie \"${cookies}\" -H \"Content-type\":\"${ContentType}\" -d \"${para}\" ${url}" >> /bin/testShell/apiCheck_shell/logs/apiCheck${day}.log
        	result=$(curl --connect-timeout ${max_time} -m ${max_time} -s -i -X POST --cookie "${cookies}" -H "Content-type":"${ContentType}" -d "${para}" ${url})
	elif [[ "${url}" =~ "?" ]]
	then
        	echo "$(date "+%Y-%m-%d %H:%M:%S"):  curl --connect-timeout ${max_time} -m ${max_time} -s -i -X GET -H \"Content-type\":\"${ContentType}\" ${url}${para}" >> /bin/testShell/apiCheck_shell/logs/apiCheck${day}.log
        	result=$(curl --connect-timeout ${max_time} -m ${max_time} -s -i -X GET -H "Content-type":"${ContentType}" ${url}${para})
	else
        	echo "$(date "+%Y-%m-%d %H:%M:%S"):  curl --connect-timeout ${max_time} -m ${max_time} -s -i -X POST -H \"Content-type\":\"${ContentType}\" -d \"${para}\" ${url}" >> /bin/testShell/apiCheck_shell/logs/apiCheck${day}.log
        	result=$(curl --connect-timeout ${max_time} -m ${max_time} -s -i -X POST -H "Content-type":"${ContentType}" -d "${para}" ${url})
	fi
	result="{${result#*\{}"
	result="${result%\}*}}"
	echo "$(date "+%Y-%m-%d %H:%M:%S"):【RESULT】${result}" >> /bin/testShell/apiCheck_shell/logs/apiCheck${day}.log
}
# 参数处理  获取para,并替换里面的省、市、区、街道、地址,如果需要进行URLEnCode,则进行URL编码
paraSeting()
{
	para=${line%|*}
        para=${para#*|}
        #cityCode=${line2%%,*}
        #adcode=$(grep "${cityCode}" /bin/testShell/apiCheck_shell/codes.csv)
        #adcode=${adcode##*,}
        #line2=${line2#*,}
        #province=${line2%%,*}
        #line2=${line2#*,}
        #cityName=${line2%%,*}
        #line2=${line2#*,}
        #area=${line2%,*}
        #line2=${line2#*,}
        #street=${line2}
        #address=${province}${cityName}${area}${street}
        if [[ ${para} =~ "URLENCODE-GB2312-" ]]
        then
        	address=${para#*URLENCODE-GB2312-}
		address=${address%&*}
		urlEncodeaddress=$(java -jar /bin/testShell/apiCheck_shell/urlEncode-1.0.0.jar ${address} GB2312)
		para=${para//"URLENCODE-GB2312-"/""}
		para=${para//"${address}"/"${urlEncodeaddress}"}
        fi
        #para=${para//ADDRESS/${address}}
        #para=${para//CITYCODE/${cityCode}}
        #para=${para//ADCODE/${adcode}}
        #para=${para//PROVINCE/${province}}
        #para=${para//CITYNAME/${cityName}}
        #para=${para//AREA/${area}}
}
# 获取check.conf中配置为ON的项目数
getProjectNum()
{
	projectList=$(grep "ON=" /bin/testShell/apiCheck_shell/check.conf)
	projectList=${projectList#*ON=}
}
#遍历api.conf中的所有接口记录
traverseApi()
{
	while read line
	do
		let apiNum++
		name="${line%%】*}】"
		url=${line#*】}
		url=${url%%|*}
		returnList=${line##*|}
		cookies=`cat /bin/testShell/apiCheck_shell/project/${project}/server.conf | grep Cookies:`
		cookies=${cookies#*Cookies:}
		if [ "${line:0:1}" == "#" ]
		then
			let annotationNum++
			echo "$(date "+%Y-%m-%d %H:%M:%S"):当前行${name}被注释,不进行校验" >> /bin/testShell/apiCheck_shell/logs/apiCheck${day}.log
			continue
		fi
		# 调用参数处理函数
	        paraSeting
               	# 调用函数,发送相关请求,并记录返回结果
		send
		# 调用函数,校验返回结果
		checkResult
	done < /bin/testShell/apiCheck_shell/project/${project}/api.conf
}
# 根据断言关键字,校验返回结果
checkResult()
{
	temp_pass_return=""
	temp_fail_return=""
	temp_pass_result=""
	temp_fail_result=""
	temp_key=""
	temp_value=""
	value=""
	if [ "${returnList}" != "" ]
	then
		# 根据switch中的配置,获取断言方式:精确匹配、包含
		isExact=`cat /bin/testShell/apiCheck_shell/project/${project}/switch.conf | grep isExact=`
                isExact=${isExact#*isExact=}
		for return in $returnList
		do
			return=${return//"\\"/"\\\\\\"}   # 针对期望值中有反斜杠的情况作特殊处理
			if [ "$isExact" == "No" ]  # 断言方式为:包含
        	        then
	                        # 如果返回的结果中包含断言关键字return,则获取断言关键字return对应的value
                        	if [[ $result =~ $return ]]
                	        then
        	                        value=${result#*${return}\":\"}
	                                value=${value%%\"*}
                                	# 根据switch中的配置,判断是否要作去空格处理
                        	        isTrim=`cat /bin/testShell/apiCheck_shell/project/${project}/switch.conf | grep isTrim=`
                	                isTrim=${isTrim#*isTrim=}
        	                        if [ "${isTrim}" == "Yes" ]
	                                then
                                	        value=${value// /}
                        	        fi
                	        fi
        	                if [ "${value}" != "" ]
	                        then
					temp_pass_return="${temp_pass_return} ${return}"
					temp_pass_result="${temp_pass_result} \"${return}\":\"${value}\""
	                        else
					temp_fail_return="${temp_fail_return} ${return}"
                                        temp_fail_result="${temp_fail_result} \"${return}\":\"${value}\""
                        	fi
                	else    # 断言方式为:精确匹配
        	                if [[ $result =~ $return ]]
	                        then
					return=${return//"\\\\"/"\\"}
					temp_pass_return="${temp_pass_return} ${return}"
					temp_key="${return%:*}"
					temp_value="${result#*${temp_key}:}"
					temp_value="${temp_value%%,*}"
					temp_key=${temp_key//"\\\\"/"\\"}
                                        temp_pass_result="${temp_pass_result} ${temp_key}:${temp_value}"
	                        else
					return=${return//"\\\\"/"\\"}
					temp_fail_return="${temp_fail_return} ${return}"
					temp_key="${return%:*}"
                                        temp_value="${result#*${temp_key}:}"
                                        temp_value="${temp_value%%,*}"
					temp_key=${temp_key//"\\\\"/"\\"}
                                        temp_fail_result="${temp_fail_result} ${temp_key}:${temp_value}"
                        	fi
                	fi
		done
		# 如果temp_fail_return长度大于0,则表示有校验失效
		if [ ${#temp_fail_return} -gt 0 ]
		then
			let failNum++
                        echo "$(date "+%Y-%m-%d %H:%M:%S"): ${name}${url}【返回异常!】" >> /bin/testShell/apiCheck_shell/logs/apiCheck${day}.log
                        echo "$(date "+%Y-%m-%d %H:%M:%S"):============================================================================================================================" >> /bin/testShell/apiCheck_shell/logs/apiCheck_err.log
                        echo "$(date "+%Y-%m-%d %H:%M:%S"): 【PARA】${para}" >> /bin/testShell/apiCheck_shell/logs/apiCheck_err.log
                        echo "$(date "+%Y-%m-%d %H:%M:%S"): 【RESULT】${result}" >> /bin/testShell/apiCheck_shell/logs/apiCheck_err.log
                        echo "$(date "+%Y-%m-%d %H:%M:%S"): ${name}${url}【返回异常!】" >> /bin/testShell/apiCheck_shell/logs/apiCheck_err.log
                        echo -e "$(date "+%Y-%m-%d %H:%M:%S"): ${name}${url}\033[41;37m 【返回异常!】 \033[0m"
                        failList="${failList}${name}${url}【返回异常!】\n"
		else
			let passNum++
                        echo "$(date "+%Y-%m-%d %H:%M:%S"): ${name}${url}【可正常访问】" >> /bin/testShell/apiCheck_shell/logs/apiCheck${day}.log
                        echo -e "$(date "+%Y-%m-%d %H:%M:%S"): ${name}${url}\033[42;37m 【可正常访问】 \033[0m"
		fi
		echo "$(date "+%Y-%m-%d %H:%M:%S"): 【PARA】${para}"
                echo -e "$(date "+%Y-%m-%d %H:%M:%S"): 【预期结果】\033[42;37m${temp_pass_return}\033[0m \033[41;37m${temp_fail_return}\033[0m"
                for temp_pass in ${temp_pass_result}
                do	
                	result=${result//"${temp_pass}"/"\033[42;37m${temp_pass}\033[0m"}
                done
                for temp_fail in ${temp_fail_result}
                do
                	result=${result//"${temp_fail}"/"\033[41;37m${temp_fail}\033[0m"}
                done
                echo -e "$(date "+%Y-%m-%d %H:%M:%S"): 【返回结果】${result}"
	fi
}
# 调用函数,获取项目数
getProjectNum
#从文件描述符管道中,获取一个管道的线程占位然后开始执行操作;read中 -u 后面跟fd,表示从文件描述符中读入,该文件描述符可以是exec新开启的
read -u6
{
	# 遍历所有状态为ON的project
	for project in $projectList
	do
		# 调用函数,遍历所有项目
		traverseApi
		echo "" >&6
		#任务执行完后在fd6中写入一个占位符,以保证这个线程执行完后,线程继续保持占位,继而维持管道中永远是thread_num个线程数,&表示该部分命令/任务放入后台不占当前的bash,实现并行处理
	done
	echo "$(date "+%Y-%m-%d %H:%M:%S"): 此次共检测接口【${apiNum}】个" >> /bin/testShell/apiCheck_shell/logs/result.log
        echo "$(date "+%Y-%m-%d %H:%M:%S"): 注释【${annotationNum}】个" >> /bin/testShell/apiCheck_shell/logs/result.log
        echo "$(date "+%Y-%m-%d %H:%M:%S"): 成功【${passNum}】个" >> /bin/testShell/apiCheck_shell/logs/result.log
        echo "$(date "+%Y-%m-%d %H:%M:%S"): 失败【${failNum}】个" >> /bin/testShell/apiCheck_shell/logs/result.log
        echo -e "$(date "+%Y-%m-%d %H:%M:%S"): 失败记录列表如下:${failList}" >> /bin/testShell/apiCheck_shell/logs/result.log
} &
wait       # 等待父进程的子进程都执行结束后再结束父进程
exec 6>&-  # 关闭fd6管道
SHELL自动化--接口测试的更多相关文章
- Python+reuqests自动化接口测试
		
1.最近自己在摸索Python+reuqests自动化接口测试,要实现某个功能,首先自己得有清晰的逻辑思路!这样效率才会很快! 思路--1.通过python读取Excel中的接口用例,2.通过pyth ...
 - Linux Shell 自动化之让文本飞
		
Linux Shell 自动化之让文本飞 一.前言:  作者之前在一家 IDC 从事运维兼职工作,后来因某些原因辞职开始 Python 爬虫数据分析.因为这些经历以及后续时间积累下的经验,发现好像自 ...
 - Jenkins之自动部署、代码安全扫描、自动化接口测试
		
搭建Jenkins wget -O /etc/yum.repos.d/jenkins.repo http://pkg.jenkins-ci.org/redhat/jenkins.reporpm --i ...
 - postman自动化接口测试
		
背景描述 有一个项目要使用postman进行接口测试,接口所需参数有: appid: 应用标识: sign:请求签名,需要使用HMACSHA1加密算法计算,签名串是:{appid}${url}${st ...
 - python+requests+unittest执行自动化接口测试
		
1.安装requests.xlrd.json.unittest库 <1>pip 命令安装: pip install requestspip install xlrdpip install ...
 - Hadoop实战4:MapR分布式集群的安装配置及shell自动化脚本
		
MapR的分布式集群安装过程还是很艰难的,远远没有计划中的简单.本人总结安装配置,由于集群有很多机器,手动每台配置是很累的,编写了一个自动化配置脚本,下面以脚本为主线叙述(脚本并不完善,后续继续完善中 ...
 - jmeter+maven+jenkins自动化接口测试(上)
		
代码已上传git(包括调试的jmx,jmeter相关文件等):https://gitlab.com/yinzhenzhi/jmeterandmaven 目的:现在很多人都在做自动化接口的平台,我也正在 ...
 - ShutIt:一个基于 Python 的 shell 自动化框架
		
ShutIt是一个易于使用的基于shell的自动化框架.它对基于python的expect库(pexpect)进行了包装.你可以把它看作是“没有痛点的expect”.它可以通过pip进行安装. Hel ...
 - Jenkins+SVN+Maven+shell  自动化部署实践
		
JAVA环境中利用Jenkins+svn+maven进行自动化部署实践 一. 前言2 1.介绍jenkins2 1.本地项目打包2 2.通过secureCRT工具,手动传输到服务器2 3.然后 ...
 
随机推荐
- Python网络编程:Linux epoll
			
原文地址:http://scotdoyle.com/python-epoll-howto.html 介绍 Python已于2.6版本添加访问Linux epoll库的API.这篇教程使用Python ...
 - HTML基础 结构,标题<h1>和段落<p> 写一个三毛语录
			
先看代码: <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <tit ...
 - 外包项目测试工作量评估指南&外包项目测试验收流程
			
## ### 外包项目测试工作量评估指南 1.目的 编写本指导书的目的旨在为我公司进行测试外包服务工作进行指导,帮助项目经理和相关人员编写测试方案.评估工作量.制定测试计划和测试策略等, ...
 - 牛客网NOIP赛前集训营-提高组(第六场)A-最长路
			
题目描述 有一张 n 个点 m 条边的有向图,每条边上都带有一个字符,字符用一个数字表示. 求以每个点为起点的最长路,输出走过的边的字符构成的字符串的字典序最小的方案. 为了方便,你需要这样输出方案: ...
 - 洛谷3321 SDOI2015 序列统计
			
懒得放传送[大雾 有趣的一道题 前几天刚好听到Creed_神犇讲到相乘转原根变成卷积的形式 看到这道题当然就会做了啊w 对于m很小 我们暴力找原根 如果你不会找原根的话 出门左转百度qwq 找到原根以 ...
 - centos 6.5 配置网络
			
编辑 vi /etc/sysconfig/network-scripts/ifcfg-eth0 修改内容 DEVICE="eth0" BOOTPROTO="static& ...
 - PHP 利用 curl 发送 post get del put patch 请求
			
因为需要在 php 开发中对接其它接口需要用 php curl 去对接其它接口 我把他们封装成函数 希望能对大家有所帮助. 这里面是封装好的会自动把 data 进行转成 json 格式,同时解码成 p ...
 - JSP中获取客户端或浏览端信息的方式
			
request应用:在JSP页面显示访问者IP 方式一:纯前台,不涉及后台操作.直接在jsp页面中需要显示IP的地方使用 代码:<%=request.getRemoteAddr()%> ...
 - 2-prometheus各组件安装
			
相关下载: https://prometheus.io/download/https://github.com/prometheus/ 相关文档 https://songjiayang.gitbook ...
 - python中遍历列表字典元组
			
遍历列表,打印:我叫name,今年age岁,家住dizhi,电话phone lt = [ {'name':'小王', 'age':18, 'info':[('phone', '123'), ('diz ...