接口测试学习-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函数

 

posted on 2018-06-01 23:03  四方城郭  阅读(835)  评论(0编辑  收藏  举报