【Python】 简易实现接口测试自动化

实现思路

使用excel管理用例用例信息,requests模块发送http请求,实现了记录日志,邮件发送测试报告的功能

目录结构如下:

【Python】 简易实现接口测试自动化

下面直接上代码:

统筹脚本

# -*- coding:utf-8 -*-
import os
from interface import Interface
from testcase_get import Get_testcase
from result_save import Save_test_result
from result_send import Send_report
from config.config import Config
from logging_save import logger if __name__ == "__main__":
cur_path = os.path.split(os.path.realpath(__file__))[0] # 获取当前文件绝对路径
case_path = os.path.join(cur_path, "test_case", "20170602.xls")
test_case = Get_testcase(case_path).readExcel() # 获取用例
if not isinstance(test_case, list): # 判断用例是否获取成功
logger.info("Test_case get failed... \n Done!")
else:
logger.info("获取用例成功")
# 调用接口
test_result = Interface().interfaceTest(test_case)
# 获取执行结果,用于发邮件
count_success = test_result[3]
count_failure = test_result[4]
failed_case_detail = test_result[5]
# 保存测试结果
Save_test_result().save_result(case_path, test_result[0], test_result[1], test_result[2])
logger.info("保存测试结果成功")
# 获取邮件配置信息
mail_config = Config(os.path.join(cur_path, "config", "mail.conf")).get_mail_config()
logger.info("获取邮箱配置成功")
login_user = mail_config[0]
login_pwd = mail_config[1]
from_addr = mail_config[2]
to_addrs = mail_config[3]
smtp_server = mail_config[4]
mail_send = Send_report(count_success, count_failure, failed_case_detail)
# 获取最新测试报告
last_report = mail_send.newest_report()
logger.info("邮件发送结果")
mail_send.send_result(login_user, login_pwd,from_addr, to_addrs,smtp_server,last_report)
logger.info("DONE!")

请求封装

# coding:utf-8
import json
import requests from logging_save import logger
from result_check import Result_check
from url_transform import urltransform class Interface:
def __init__(self, ):
pass def interfaceTest(self, case_list):
"""
接口调用主函数
"""
# 用于存结果
res_flags = []
# 用于存请求报文
request_urls = []
# 用于存返回报文
responses = []
# 用户存失败的用例
failed_case = []
# 统计成功失败的用例数
count_success = 0
count_failure = 0
for case in case_list:
try:
# 模块
product = case[0]
# 用例id
case_id = case[1]
# 用例标题
interface_name = case[2].strip('\n')
# 用例描述
case_detail = case[3]
# 请求方式
method = case[4]
# 请求url
url = case[5]
# 入参
param = case[6]
# 预期结果
res_check = case[7]
except Exception as e:
return '测试用例格式不正确!%s' % e
# 定义消息头信息
headers = {'content-type': 'application/json',
'User-Agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:22.0) Gecko/20100101 Firefox/22.0'}
# 对url进行封装
new_url = urltransform().urltransform(url, method, param)
if method.upper() == 'GET':
results = requests.get(new_url).text
logger.info(u'正在调用接口: %s' % interface_name)
# print results
responses.append(results)
# 用于存储预期结果与实际结果的比较结果
res = Result_check().interface_result_check(results, res_check)
request_urls.append(new_url)
else:
request_urls.append(new_url)
if param == '':
pass
else:
data = json.loads(param) # 将参数转化为json格式
results = requests.post(new_url, data=json.dumps(data), headers=headers).text
responses.append(results)
res = Result_check().interface_result_check(results, res_check)
if 'pass' in res:
res_flags.append('pass')
count_success += 1
else:
logger.warning(u'接口返回结果与预期结果不一致!失败URL: %s METHOD :%s' % (url, method))
res_flags.append('fail')
count_failure += 1
failed_case.append((interface_name, method, url))
logger.info(u'共执行 %s 条用例,PASS: %s,FAILED: %s' % (len(case_list), count_success, count_failure))
return res_flags, request_urls, responses, count_success, count_failure, failed_case

日志封装

# coding=utf-8
import logging
import sys
import traceback
import time class LoggingUtils:
'''
===========封装日志工具类的基本操作=============
'''
def __init__(self,logfile):
'''
:param logfile:
'''
self.logger = logging.getLogger(logfile)
self.hdlr = logging.FileHandler(logfile)
formatter = logging.Formatter('%(asctime)s %(levelname)s - %(message)s')
self.ch = logging.StreamHandler()
self.ch.setLevel(logging.INFO)
self.ch.setFormatter(formatter)
self.hdlr.setFormatter(formatter)
self.logger.addHandler(self.hdlr)
self.logger.addHandler(self.ch)
self.logger.setLevel(logging.DEBUG) def debug(self, msg):
'''
:param msg:
:return:
'''
self.logger.debug(msg)
self.hdlr.flush() def info(self, msg):
''' :param msg:
:return:
'''
self.logger.info(msg)
self.hdlr.flush() def warning(self,msg):
self.logger.warning(msg)
self.hdlr.flush() def error(self, msg):
''' :param msg:
:return:
'''
self.logger.error(msg)
# self.logger.removeHandler(logging.StreamHandler())
self.logger.removeHandler(self.ch)
self.hdlr.flush() def error_sys(self, limit=None):
'''
:param limit:
:return:
'''
exceptionType, exceptionValue, exceptionTraceback = sys.exc_info()
if limit is None:
if hasattr(sys, 'tracebacklimit'):
limit = sys.tracebacklimit
n = 0
eline = '\n'
while exceptionTraceback is not None and (limit is None or n < limit):
f = exceptionTraceback.tb_frame
lineno = exceptionTraceback.tb_lineno
co = f.f_code
filename = co.co_filename
name = co.co_name
eline += ' File "%s", line %d, in %s \n ' % (filename, lineno, name)
exceptionTraceback = exceptionTraceback.tb_next
n = n + 1 eline += "\n".join(traceback.format_exception_only(exceptionType, exceptionValue))
self.logger.error(eline)
self.hdlr.flush()
timer = time.strftime('%Y-%m-%d',time.localtime())
logger = LoggingUtils('%s.log'%timer)

结果比对

#coding:utf-8
class result_check(): def __init__(self):
pass def result_check(self,results,res_check):
'''
结果对比函数
'''
#返回结果,将结果中的json数据转化为可以和预期结果比较的数据
res = results.replace('":"','=').replace('" : "','=')
#预期结果,是xx=11;xx=22
res_check = res_check.split(';')
for s in res_check:
if s in res:
pass
else:
return '结果不匹配 '+ str(s)
return 'pass'
result_save.py 保存测试结果的模块,复制原有的用例,保存为新的excel
#coding:utf-8
from xlutils import copy
import xlrd
import time
import os class Save_test_result(): def __init__(self):
pass def save_result(self,file_path,res_flags,request_urls,responses):
'''
:return:
'''
book = xlrd.open_workbook(file_path)
new_book = copy.copy(book)
sheet = new_book.get_sheet(0)
i = 1
for request_url, response, flag in zip(request_urls, responses, res_flags):
sheet.write(i, 8, u'%s' % request_url)
sheet.write(i, 9, u'%s' % response)
sheet.write(i, 10, u'%s' % flag)
i += 1
report_path = os.path.abspath(os.path.join('report'))
if not os.path.exists(report_path):
os.makedirs(report_path)
new_book.save(os.path.abspath(os.path.join(report_path, 'Report@%s.xls' % time.strftime('%Y.%m.%d@%H%M%S'))))

结果邮件

#coding:utf-8
import smtplib
from email.mime.text import MIMEText
from email.header import Header
from email.mime.multipart import MIMEMultipart
import os
from logging_save import logger class Send_report(object):
def __init__(self,count_success,count_failure,failed_case):
'''
:param count_success:
:param count_failure:
:param failed_case:
'''
self.count_success = count_success
self.count_failure = count_failure
self.failed_case = failed_case def newest_report(self,testreport='report'):
'''
获取最新的测试报告
:param testreport:
:return:
'''
lists = os.listdir(testreport)
lists.sort(key=lambda fn: os.path.getmtime(os.path.join(testreport,fn)))
file_new = os.path.join(testreport, lists[-1])
logger.info('获取最新附件报告成功')
return file_new def send_result(self,username,passwd,from_addr,to_addrs,smtpserver,*args):
'''
:param username:
:param passwd:
:param from_addr:
:param to_addrs:
:param smtpserver:
:param args:
:return:
'''
sender = from_addr
subject = '财富港接口测试结果'
username = username
passwd = passwd '''邮件内容'''
tille = (u'用例名称', u'请求方式', u'url')
details = (u'成功: ' + str(self.count_success) + u'失败: ' + str(self.count_failure)) + '\n' + u'失败的用例如下 :' + \
'\n' + '\n'.join(str(zip(tille, i)) for i in self.failed_case).decode('unicode-escape')
logger.info('邮件附件为: %s' %(args[0].split('\\')[1])) if args != None: #判断是否添加附件
msg = MIMEMultipart()
msg.attach(MIMEText(details, 'plain', 'utf-8'))
i = 0
while i < len(args): #可以添加多个附件
part = MIMEText(open(args[i], 'rb').read(), 'base64', 'utf-8')
part["Content-Type"] = 'application/octet-stream'
part["Content-Disposition"] = 'attachment; filename="%s"'%args[i]
msg.attach(part) #添加附件
i += 1 msg['subject'] = Header(subject, 'utf-8')
msg['From'] = from_addr
msg['To'] = ','.join(eval(to_addrs)) #兼容多个收件人
smtp = smtplib.SMTP()
try:
smtp.connect(smtpserver)
smtp.login(username, passwd)
smtp.sendmail(sender, eval(to_addrs), msg.as_string())
smtp.close()
logger.info('带附件测试报告发送成功!')
except smtplib.SMTPAuthenticationError,e:
logger.error('邮箱账户或密码错误: '+ str(e)) else:
msg = MIMEText(details, 'plain', 'utf-8')
msg['subject'] = Header(subject, 'utf-8')
msg['From'] = from_addr
msg['To'] = ','.join(eval(to_addrs))
smtp = smtplib.SMTP()
try:
smtp.connect(smtpserver)
smtp.login(username, passwd)
smtp.sendmail(sender, eval(to_addrs), msg.as_string())
logger.info('测试报告发送成功!')
smtp.close()
except smtplib.SMTPAuthenticationError,e:
logger.error('邮箱账户或密码错误 : '+str(e))

用例获取及数据格式化

#coding:utf-8
import xlrd from logging_save import logger class Get_testcase(object): def __init__(self, file_path):
'''
:param file_path: 用例文件路径
'''
self.file_path = file_path def readExcel(self):
'''
读取用例函数
:return: 测试用例列表
'''
try:
book = xlrd.open_workbook(self.file_path) # 打开excel
except Exception, error:
logger.error('路径不在或者excel不正确 : ' + str(error))
return error
else:
sheet = book.sheet_by_index(0) # 取第一个sheet页
rows = sheet.nrows # 取这个sheet页的所有行数
case_list = [] # 用于保存用例信息
for i in range(rows):
if i != 0:
case_list.append(sheet.row_values(i)) # 把每一条测试用例添加到case_list中
return case_list

请求url转换

#coding:utf-8
class urltransform(object):
def __init__(self):
pass def urltransform(self, url, method, param):
'''
:return:
'''
if param == '':
new_url = url
else:
if method.upper() == 'GET':
new_url = url + '?' + param.replace(';', '&') #如果有参数,且为GET方法则组装url
else:
new_url = url
return new_url

测试用例excel结构

【Python】 简易实现接口测试自动化

config目录下,config.py   获取配置文件信息的模块

#conding:utf-8
import ConfigParser class Config(object): def __init__(self,file_path):
self.config = ConfigParser.ConfigParser()
self.config.read(file_path) def get_mail_config(self):
login_user = self.config.get('SMTP', 'login_user')
login_pwd = self.config.get('SMTP', 'login_pwd')
from_addr = self.config.get('SMTP', 'from_addr')
to_addrs = self.config.get('SMTP', 'to_addrs')
smtp_server = self.config.get('SMTP', 'smtp_server')
port = self.config.get('SMTP', 'port')
return login_user, login_pwd , from_addr, to_addrs,smtp_server, port def report_save_config(self):
pass

mail.conf

[SMTP]
login_user = 18******@163.com
login_pwd = ******
from_addr = BI<18******@163.com>
to_addrs = ['18******@163.com']
#to_addrs = ['1******@qq.com','******.com']
smtp_server = smtp.163.com
port = 25

测试报告

【Python】 简易实现接口测试自动化

邮件接收结果

aaarticlea/png;base64,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" alt="" />

上一篇:网络AFNetworking 3.1


下一篇:hive 将一个分区表数据全部插入另外一个分区表