zoukankan      html  css  js  c++  java
  • python实现http接口自动化测试(完善版)

    今天给大家分享一个简单的Python脚本,使用python进行http接口的自动化测试,脚本很简单,逻辑是:读取excel写好的测试用例,然后根据excel中的用例内容进行调用,判断预期结果中的返回值和返回报文中的值是否一致,如果不一致则根据用例标题把bug提交到bug管理系统,这里使用的bug管理系统是bugfree。最后统计测试结果:总共执行多少条用例、通过多少条用例,失败多少条用例,邮件标题加上当前时间,将测试结果发送到指定邮箱。

    实现步骤:

                   1、读取excel,保存测试用例中的内容,这里需要定义一个读取excel的函数readExcel();

                   2、根据excel中的请求url和参数拼接请求报文,调用接口,并保存返回报文,这里需要定义一个将请求数据转换为字典的函数param_To_Dic();

                   3、读取返回报文,和预期结果对比,不一致的往bugfree数据库中写入一条bug,并且把请求报文、返回报文和测试结果写到测试用例的excel中,这里需要定义一个比对预期结果和返回结果的函数contrastRes(),一个往bugfree提交bug的函数writeBug(),一个将测试结果写入excel的函数copy_excel(),还需定义一个接口请求的函数interfaceTest()。

                   4、统计测试结果,发送测试邮件。需定义一个send_email()的函数。

    http接口最常用的两种请求方式,POST和GET两种方法,这篇博客分享的就是最简单常用的url请求。例如:http://192.168.21.129/bugfree/index.php/info/edit?type=bug&action=opened&product_id=1

    需要用的到几个模块有:requests、xlrd(读取excel)、xlutils(写excel)、pymysql(连接数据库)、yagmail(发送邮件)这五个模块都是第三方模块,需要自己单独安装。

    首先在excel中写好用例,需要有的字段 项目、用例id、接口名称、用例描述、请求方式、请求url、请求数据(多个的参数话用&分号隔开)、预期结果、请求报文、返回报文、测试人员、测试结果

    首先我们将项目框架建起来,如下图所示:

    cases目录中是放excel测试用例,conf文件夹是配置文件,lib目录是存放主逻辑的,logs目录里是日志文件,bin目录下是启动文件,运行start.py即可运行该项目

    1.excel中测试用例书写格式如下图所示:

    2.我们编写lib中的主逻辑,将上面分析出的所需要的函数写在common.py中,代码如下:

    class OpCase(object):
    def get_case(self,file_path):
    cases = [] #存放所有的case
    if file_path.endswith('.xls') or file_path.endswith('.xlsx'):
    try:
    book = xlrd.open_workbook(file_path)
    sheet = book.sheet_by_index(0)
    for i in range(1,sheet.nrows):
    row_data = sheet.row_values(i)
    cases.append(row_data[4:11])
    atp_log.info('共读取%s条用例'%(len(cases)))
    self.file_path = file_path
    except Exception as e:
    atp_log.error('【%s】用例获取失败,错误信息:%s'%(file_path,e))
    else:
    atp_log.error('用例文件不合法的,%s'%file_path)
    return cases

    def my_request(self,url,method,data=None,cookie=None,header=None,files=None,is_json=False ):
    method = method.upper()
    data = self.dataToDict(data)
    cookie = self.dataToDict(cookie)
    header = self.dataToDict(header)
    files = self.dataToDict(files)
    atp_log.debug('【files转为字典后是:%s】' % files)
    data = data if data else {}
    cookie = cookie if cookie else {}
    header = header if header else {}
    if files:
    files = {
    "file":open(files['files'],"rb")
    }
    else:
    files = {}
    try :
    if method=='POST':
    try:
    if is_json:
    res = requests.post(url, json=data, cookies=cookie, headers=header, files=files,verify=False).text
    else:
    res = requests.post(url, data=data, cookies=cookie, headers=header, files=files,verify=False).text
    atp_log.debug('【接口返回数据:%s】' % res)
    print('res...', res)
    except Exception as e:
    res = str(e) # 如果接口调用出错的话,那么就返回一个有错误信息的字典
    atp_log.error('异常信息:接口调用失败! url 【%s】 data 【%s】 实际结果是 【%s】' % (url, data, res))
    elif method=='GET':
    try:
    # verify=False 的意思就是https能访问
    res = requests.get(url, params=data, cookies=cookie, headers=header, verify=False).text
    atp_log.debug('【接口返回数据:%s】' % res)
    except Exception as e:
    res = str(e) # 如果接口调用出错的话,那么就返回一个有错误信息的字典
    atp_log.error('异常信息:接口调用失败! url 【%s】 data 【%s】实际结果是 【%s】' % (url, data,res))
    return res
    else:
    atp_log.warning('该请求方式暂不支持。。')
    res = '该请求方式暂不支持。。'
    except Exception as e:
    msg = '【%s】接口调用失败,%s'%(url,e)
    atp_log.error(msg)
    res = msg
    return res

    def check_res(self,res,check):
    res = res.replace('": "','=').replace('": ','=')
    for c in check.split(','):
    if c not in res:
    atp_log.info('结果校验失败,预期结果:【%s】,实际结果【%s】'%(c,res))
    return '失败'
    return '成功'

    def write_excel(self,cases_res):
    # [ ['dsfd',"通过"] ,['sdfsdf','失败'] ]
    book = xlrd.open_workbook(self.file_path)
    new_book = copy.copy(book)
    sheet = new_book.get_sheet(0)
    row = 1
    for case_case in cases_res:
    sheet.write(row,11,case_case[0]) #写第11列
    sheet.write(row,12,case_case[1]) #写第12列
    row+=1
    new_book.save(self.file_path.replace('xlsx','xls'))

    def dataToDict(self,data=None):
    if data:
    #把数据转成字典
    res = {}
    data = data.split(',')
    for d in data:
    #a=
    k,v = d.split('=')
    res[k]=v
    return res

     3.写日志的模块,代码如下:

        可以引用一个简单的log模块,只需要pip install nnlog即可使用,详细教程参照牛牛博客:www:nnzhp.cn/archives/646

    class MyLogger():
        def __init__(self,file_name,level='info',backCount=5,when='D'):
            logger = logging.getLogger()  # 先实例化一个logger对象,先创建一个办公室
            logger.setLevel(self.get_level(level))  # 设置日志的级别的人
            cl = logging.StreamHandler()  # 负责往控制台输出的人
            bl = handlers.TimedRotatingFileHandler(filename=file_name, when=when, interval=1, backupCount=backCount, encoding='utf-8')
            fmt = logging.Formatter('%(asctime)s - %(pathname)s[line:%(lineno)d] - %(levelname)s: %(message)s')
            cl.setFormatter(fmt)  # 设置控制台输出的日志格式
            bl.setFormatter(fmt)  # 设置文件里面写入的日志格式
            logger.addHandler(cl)
            logger.addHandler(bl)
            self.logger = logger
    
        def get_level(self,str):
            level = {
                'debug':logging.DEBUG,
                'info':logging.INFO,
                'warn':logging.WARNING,
                'error':logging.ERROR
            }
            str = str.lower()
            return level.get(str)
    
    path = os.path.join(setting.LOG_PATH,setting.LOG_NAME) #拼好日志的绝对路径
    atp_log = MyLogger(path,setting.LEVEL).logger
    #直接在这里实例化,用的时候就不用再实例化了

    4.发送邮件函数,代码如下:

    def sendmail(title,content,attrs=None):
        m = yagmail.SMTP(host=setting.MAIL_HOST,user=setting.MAIL_USER
                     ,password=setting.MAIL_PASSWORD,smtp_ssl=True
                     )
        m.send(to=setting.TO,subject=title,
               contents=content,
               attachments=attrs)
        atp_log.info('发送邮件完成')

    5.conf中配置文件进行参数的配置,详细如下:

    import os
    BASE_PATH = os.path.dirname(
        os.path.dirname(os.path.abspath(__file__))
    )
    MAIL_HOST='smtp.qq.com'
    MAIL_USER='729111761@qq.com'
    MAIL_PASSWORD = 'xxxxxxxxxxx'
    TO = [
        '1379440856@qq.com',
    ]
    LEVEL = 'debug' #日志级别
    
    LOG_PATH = os.path.join(BASE_PATH,'logs') #存放日志的路径
    CASE_PATH = os.path.join(BASE_PATH,'cases') #存放日志的路径
    LOG_NAME='atp.log' #日志的文件名

    6.最后就是bin目录下的运行文件start.py,代码如下:

    
    
    BASE_PATH = os.path.dirname(
    os.path.dirname(os.path.abspath(__file__))
    )
    sys.path.insert(0,BASE_PATH)

    from lib.common import OpCase
    from lib.send_mail import sendmail
    from conf import setting
    class CaseRun(object):
    def find_cases(self):
    op = OpCase()
    for f in os.listdir(setting.CASE_PATH):#每次循环的时候读一个excel
    abs_path = os.path.join(setting.CASE_PATH,f)
    case_list = op.get_case(abs_path)
    res_list = []
    pass_count,fail_count = 0,0
    for case in case_list:#循环每个excel里面所有用例
    url,method,req_data,cookie,header,files,check = case
    res = op.my_request(url, method, req_data, cookie, header, files) # 调用完接口返回的结果
    status = op.check_res(res,check)
    res_list.append([res,status])
    if status=='成功':
    pass_count+=1
    else:
    fail_count+=1
    op.write_excel(res_list) #写入excel
    msg = '''
    xx你好:
    本次共运行%s条用例,通过%s条,失败%s条。
    '''%(len(res_list),pass_count,fail_count)
    # sendmail('测试用例运行结果',content=msg,attrs=abs_path)
    CaseRun().find_cases()
     

    7.另外readme里面可以简单介绍下该框架的运行环境,所依赖的模块,简单的思路和顺序。

    自此,基于数据驱动的接口自动化测试框架就已搭建成功,大家可以自己动手试试了。。。。

  • 相关阅读:
    JavaFX 1.2 SDK 发布,增加 Linux 及 OpenSolaris 支持
    JSF 2.0 通过最终投票
    NetBeans 时事通讯(刊号 # 57 May 27, 2009)
    “C语言” 读书札记(六)之[Linux下C语言编程环境Make命令和Makefile] 川山甲 博客园
    [转]宽字符的介绍
    【语法回顾】C++STL:string类型 ATP_ 博客园
    Using the C/C++ Garbage Collection Library, libgc
    Makefile学习笔记 我的CPP之路 C++博客
    伍迷创意随想集 之 杯具拥有个性,个性成就杯具 伍迷 博客园
    知哈希算法——找出相似的图片
  • 原文地址:https://www.cnblogs.com/mululu/p/9146749.html
Copyright © 2011-2022 走看看