zoukankan      html  css  js  c++  java
  • 接口测试学习-python第八课(数据驱动测试)

    自动化分为三类,数据驱动即根据数据去进行测试;代码驱动即测试都是通过代码完成的;关键字驱动即依靠一些软件,利用关键字完成测试。本次主要记录数据驱动,自动化框架主要有以下几个部分:
    ①获取用例
    ②调用接口
    ③检验结果
    ④发送测试报告
    ⑤异常处理
    ⑥日志

    以前进行接口封装的时候,有过将代码分别放在不同的文件夹下的经历。这次也以这样的模式来完成,主要做到以下几点:首先读取excel文件里面的用例,其次根据用例完成接口测试,然后将测试返回信息和测试结果写入到excel用例文件中,最后发送邮件。同时各个部分关键结果处需要记录日志。

    1、setting文件

    setting文件一般放在config文件夹下。这个代码因为涉及到发送邮件,读取excel,写日志等。所以基础数据包括邮件的host,账号,密码等;还有文件地址和日志地址等。这些数据在后面的代码中都会使用到。

     1 import os
     2 
     3 
     4 # 发送邮件的一些固定参数,在sendmail函数中会使用到,可以在此处修改,此处的password是授权码
     5 MAIL_HOST = 'smtp.163.com'
     6 MAIL_USER = '********@163.com'
     7 MAIL_PASSWORD = *****'  # 授权码
     8 MAIL_TO = '352780148@qq.com'
     9 
    10 BASE_PATH = os.path.dirname(
    11     os.path.dirname(os.path.abspath(__file__))
    12 )  # 找到APT这个文件夹的地址
    13 LOG_PATH = os.path.join(BASE_PATH, 'logs')  # 拼接出存放日志的路径
    14 CASE_PATH = os.path.join(BASE_PATH, 'cases')  # 拼接出存放用例的路径
    15 
    16 LEVEL = 'debug'  # 日志级别
    17 LOG_NAME = 'apt.log'  # 日志文件名

    2、日志模块

    这个模块主要内容就是日志记录的功能。构造了一个可实例化的类,实例化后在其他模块可以直接调用生成相应等级的日志。

     1 import logging
     2 import os
     3 from logging import handlers
     4 from config import setting
     5 
     6 
     7 class MyLogger(object):
     8     def __init__(self,file_name,level='info',backCount=5,when='D'):
     9         logger = logging.getLogger()
    10         logger.setLevel(self.get_level(level))  # 设置日志的级别
    11         # fl = logging.FileHandler(filename='a.log', mode='a', encoding='utf-8')
    12         cl = logging.StreamHandler()  # 负责往控制台输出的
    13         bl = handlers.TimedRotatingFileHandler(filename=file_name, when=when, interval=1,
    14                                                backupCount=backCount, encoding='utf-8')
    15         fmt = logging.Formatter('%(asctime)s - %(pathname)s[line:%(lineno)d]-%(levelname)s:%(message)s')
    16         # 指定日志的格式
    17         cl.setFormatter(fmt)  # 设置控制台输出的日志格式
    18         bl.setFormatter(fmt)  # 设置文件里面写入的日志格式
    19         logger.addHandler(cl)  # 把已经设置好的人放到办公室中
    20         logger.addHandler(bl)  # 同上
    21         self.logger = logger
    22 
    23     def get_level(self, sss):
    24         level = {
    25             'debug': logging.DEBUG,
    26             'info': logging.INFO,
    27             'warn': logging.WARN,
    28             'error': logging.ERROR
    29         }
    30         sss = sss.lower()
    31         return level.get(sss)
    32 
    33 path = os.path.join(setting.LOG_PATH,  setting.LOG_NAME)  # 拼好日志的绝对路径
    34 apt_log = MyLogger(path, setting.LEVEL).logger
    35 # 直接在这边实例化,并.logger,使用时就可以直接apt_log.warning了

    3、发送邮件模块

    用于记录发送邮件的功能,这里就用到了setting里面记录的那些基础数据,还用到了日志记录功能。

     1 import yagmail
     2 from config import setting
     3 from lib.log import apt_log
     4 
     5 
     6 def sendemile(title, content, attrs=None):  # 定义发送邮件函数
     7     m = yagmail.SMTP(host=setting.MAIL_HOST,  # host调用setting文件中设置的固定参数
     8                      user=setting.MAIL_USER,  # user调用setting文件中设置的固定参数
     9                      password=setting.MAIL_PASSWORD  # password调用setting文件中设置的固定参数
    10                      )
    11     m.send(to=setting.MAIL_TO,
    12            subject=title,
    13            contents=content,
    14            attachments=attrs
    15            )  # 邮件发送主体内容,收件人使用固定参数,其他内容在调用函数时传入
    16     apt_log.info('邮件发送成功。')  # 写入发送邮件成功的日志

    4、读取用例进行测试并记录测试结果模块

    这是一个主体模块,完成了这个文件的主要功能。详细代码如下。

     1 import xlrd
     2 from lib.log import apt_log
     3 import requests
     4 from xlutils import copy
     5 
     6 
     7 class OpCase(object):
     8     def get_case(self, file_path):
     9         cases = []  # 存放所有的测试用例
    10         if file_path.endswith('.xls') or file_path.endswith('.xlsx'):  # 判断路径是否存在
    11             try:
    12                 book = xlrd.open_workbook(file_path)
    13                 sheet = book.sheet_by_index(0)  # 打开用例文件
    14                 for i in range(1, sheet.nrows):  # 从第二行开始遍历excel文件内容(第一行是标题)
    15                     row_data = sheet.row_values(i)  # 获取每行内容
    16                     cases.append(row_data[4:8])  # 在cases这个list中存每个用例的url,method,req_data,check
    17                 apt_log.info('共读取%s条用例' % (len(cases)))  # 检查cases中的元素个数,日志记录读取了几条用例
    18                 self.file_path = file_path  # 既然读取成功说明这个文件路径是正确的,那么这边定义下面写exccel就可以直接使用了
    19             except Exception as e:
    20                 apt_log.error('【%s】用例打开失败,错误信息:%s' % (file_path, e))
    21         else:
    22             apt_log.error('用例文件不合法,%s' % file_path)
    23         return cases
    24 
    25     def dataToDict(self, data):  # 将用例中的req_data转为字典格式,可以直接用在request模块
    26         res = {}
    27         data = data.split(',')  # 这个地方要求用例中请求参数使用英文逗号分割的
    28         # 这边分割入参后,入参变为['a=1', 'b=2']这样的格式
    29         for d in data:
    30             k, v = d.split('=')
    31             # 再次分割后变为['a','1']这样的模式分别用k代表a,v代表1
    32             res[k] = v  # 存入字典中变成'a':1,这样的模式可直接在request模块接口测试中作为入参使用
    33         return res
    34 
    35     def my_request(self, url, method, data):
    36         method = method.upper()  # 首先将请求方式变为大写模式,方便后面验证
    37         data = self.dataToDict(data)  # 把a=1,b=2格式的请求参数变成字典格式
    38         try:
    39             if method == 'POST':
    40                 res = requests.post(url, data).text  # 如果请求方式是post按照post模式进行接口测试
    41             elif method == 'GET':
    42                 res = requests.get(url, data).text  # 按照get方式传入url和data进行接口测试
    43             else:
    44                 apt_log.warning('暂不支持该请求')  # 其他的请求方式不支持,打印日志并返回提示
    45                 res = '暂不支持该请求'
    46         except Exception as e:
    47             msg = '【%s】接口调用失败,%s' % (url, e)  # 请求未成功提示接口调用失败,写入日志并返回提示
    48             apt_log.error(msg)
    49             res = msg
    50         return res
    51 
    52     def check_res(self, res, check):
    53         res.replace('": "', '=').replace('": ', '=')  # 返回的报文是json格式的,利用字符替换让数据变成"a=1,b=2"的格式
    54         for c in check.split(','):  # 判断验证数据是否在返回的报文中
    55             if c not in res:
    56                 apt_log.info('结果校验失败,预期结果:【%s】,实际结果【%s】' % (c, res))  # 不匹配则测试校验失败,打印日志
    57                 return '失败'  # 返回失败的提示
    58         return '通过'  # 如果存在说明测试通过
    59 
    60     def write_excel(self, cases_res):  # 入参是每个用例的执行结果
    61         book = xlrd.open_workbook(self.file_path)
    62         new_book = copy.copy(book)
    63         sheet = new_book.get_sheet(0)  # 复制测试用例excel文件
    64         row = 1
    65         for case_res in cases_res:  # 遍历写入数据
    66             sheet.write(row, 8, case_res[0])  # 第八列写返回结果
    67             sheet.write(row, 9, case_res[1])  # 第九列写测试是否通过
    68             row += 1
    69         new_book.save(self.file_path.replace('xlsx', 'xls'))  # 保存结果
    70         

    5、start文件

    启动文件,用于集成所有的模块完成目标。

     1 import os
     2 import sys
     3 from lib.common import OpCase
     4 from lib.send_emile import sendemile
     5 from config import setting
     6 
     7 BASE_PATH = os.path.dirname(
     8     os.path.dirname(os.path.abspath(__file__))
     9 )  # 找到APT这个文件夹的地址
    10 sys.path.insert(0, BASE_PATH)  # 把ATP目录加到环境变量中,用于在其他不能帮忙加环境变量的时候
    11 
    12 
    13 class CaseRun(object):
    14     def find_cases(self):
    15         op = OpCase()  # 实例化了操作用例这个类
    16         for f in os.listdir(setting.CASE_PATH):  # 获取到cases文件夹下的文件
    17             abs_path = os.path.join(setting.CASE_PATH, f)  # 拼接测试用例文件的绝对路径
    18             case_list = op.get_case(abs_path)  # 利用get_case函数获取到每个用例中的case
    19             res_list = []  # 创建一个空的list来存放测试返回的报文和测试结果
    20             pass_count = 0  # 用来计算成功用例个数
    21             fail_count = 0  # 用来计算失败用例格式
    22             for case in case_list:
    23                 url, method, req_data, check = case  # get_case函数中提取每行用例的四个元素,分别定义一下
    24                 res = op.my_request(url, method, req_data)  # 调用my_request函数进行测试接口返回结果
    25                 status = op.check_res(res, check)  # 检查测试返回报文是否和预计测试结果相同,如果相同测试通过,否则测试失败
    26                 res_list.append([res, status])  # 为了一次性写入测试结果,先将结果放入list中
    27                 if status == '通过':
    28                     pass_count += 1
    29                 else:
    30                     fail_count += 1
    31             op.write_excel(res_list)  # 写入excel
    32             msg = '''  # 定义邮件正文
    33             XX你好:
    34                 本次共运行%s条用例,通过%s条,失败%s条。
    35                 ''' % (len(res_list), pass_count, fail_count)
    36             sendemile('测试用例运行结果', content=msg, attrs=abs_path)  # 利用sendmail函数发送邮件,入参分别是主题,内容和附件
    37 
    38 
    39 CaseRun().find_cases()  # 运行find_cases函数
  • 相关阅读:
    P1197 [JSOI2008]星球大战[并查集+图论]
    P1955 [NOI2015]程序自动分析[离散化+并查集]
    取模运算律[简单数学]
    P1462 通往奥格瑞玛的道路[最短路+二分+堆优化]
    P1330 封锁阳光大学[搜索+染色]
    P1168 中位数[堆 优先队列]
    P2661 信息传递[最小环+边带权并查集]
    P1080 【NOIP 2012】 国王游戏[贪心+高精度]
    P2085 最小函数值[优先队列]
    【转】priority_queue的用法
  • 原文地址:https://www.cnblogs.com/myyard777/p/9123945.html
Copyright © 2011-2022 走看看