zoukankan      html  css  js  c++  java
  • 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=" "
    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}33[41;37m 【返回异常!】 33[0m"
    failList="${failList}${name}${url}【返回异常!】 "
    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}33[42;37m 【可正常访问】 33[0m"
    fi
    echo "$(date "+%Y-%m-%d %H:%M:%S"): 【PARA】${para}"
    echo -e "$(date "+%Y-%m-%d %H:%M:%S"): 【预期结果】33[42;37m${temp_pass_return}33[0m 33[41;37m${temp_fail_return}33[0m"
    for temp_pass in ${temp_pass_result}
    do
    result=${result//"${temp_pass}"/"33[42;37m${temp_pass}33[0m"}
    done
    for temp_fail in ${temp_fail_result}
    do
    result=${result//"${temp_fail}"/"33[41;37m${temp_fail}33[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管道

  • 相关阅读:
    视频相关一些基础概念解析
    git
    mysql数据库查找类型不匹配
    matlab转python
    神经网络(二)
    python图片处理(三)
    python图片处理(二)
    python图片处理(一)
    python图片处理和matlab图片处理的区别
    MapReduce原理与设计思想
  • 原文地址:https://www.cnblogs.com/wenjint-one/p/11320264.html
Copyright © 2011-2022 走看看