记:一个简单的python+requests+unittest+HTMLTestRunner+发送邮件的自动化接口测试实例
最近几天,公司强制加班(新CTO上任三把火),由于上一个项目刚刚结束,最近两天并没有很忙,就趁着加班时间练了下手,简单记一下,方便回顾。PS:最XX这种强制加班了......
主要目录如下:
一、Base_page.py:封装常用的请求方式
这里只放了post()和get()的请求方式,别的请求方式编写格式类似。
import requests # 导入requests模块 import json class Base(): def method_post(self, url, params=None, data=None, headers=None, files=None): return requests.post(url=url, params=params, data=data, headers=headers, files=files) def method_get(self, url, params=None, data=None, headers=None, files=None): return requests.get(url=url, params=params, data=data, headers=headers, files=files) def requests_type(self, method, url, params=None, data=None, headers=None, files=None): if method == 'post' or method == 'POST': return self.method_post(url=url, params=params, data=data, headers=headers, files=files) elif method == 'get' or method == 'GET': return self.method_get(url=url, params=params, data=data, headers=headers, files=files) if __name__ == "__main__": s = Base() header = { 'JSESSIONID': 'xxxxxx', 'Content-Type': 'application/json;charset=UTF-8' } data = {"orderNoOrDelivery": "xxxxxxxxxxxxx"} urls = 'https://xxxxxx/findMallOrderList' response = s.requests_type(method='post', url=urls, headers=header, data=json.dumps(data)) print(response.json())
编完后,main方法调试一下~
二、commons.py:封装日志、读取Excel表方法、生成HTML报告
依次是日志保存位置,html报告保存位置,测试接口的excel表格位置
2.1 封装日志(可直接拿去用)
#封装日志方法 def get_logs(self, path=log_path): import logging, time logs = logging.getLogger() logs.setLevel(logging.DEBUG) path = path+'/' + time.strftime('%Y-%m-%d-%H-%M-%S') + '.log' write_file = logging.FileHandler(path, 'a+', encoding='utf-8') write_file.setLevel(logging.DEBUG) set_logs = logging.Formatter('%(asctime)s - %(filename)s - %(funcName)s - %(levelname)s - %(message)s') write_file.setFormatter(set_logs) pycharm_text = logging.StreamHandler() pycharm_text.setFormatter(set_logs) logs.addHandler(write_file) logs.addHandler(pycharm_text) return logs
2.2 读取Excel表方法(可直接拿去用)
返回的是一个值是字典的列表,取值的时候注意
# 读取Excel表方法,方便后续读取接口用例数据 def ReadExcelTypeDict(self, file_name, path=read_xlrd): path = path + '/' + file_name import xlrd work_book = xlrd.open_workbook(path) # 打开Excel表 sheets = work_book.sheet_names() # 获取所有的sheets页 DatasList = [] for sheet in sheets: sheets = work_book.sheet_by_name(sheet) nrows = sheets.nrows for i in range(0, nrows): values = sheets.row_values(i) DatasList.append(values) title_list = DatasList[0] content_list = DatasList[1:] new_list = [] for content in content_list: dic = {} for i in range(len(content)): dic[title_list[i]] = content[i] new_list.append(dic) return new_list
main方法看一下返回的值
2.3 生成HTML报告方法(可直接拿去用)
# 封装HTML报告方法 def GetHtmlResult(self, suite, title, path=report_html): path = path + '\\' + time.strftime('%Y-%m-%d-%H-%M-%S') + '.html' with open(path, 'wb+') as f: runner = HTMLTestReportCN.HTMLTestRunner(stream=f, description='2个查询接口测试报告', tester='酸菜', title=title) runner.run(suite)
这里用到的HTMLTestReportCN是借用他人优化过的文件,有需要可以更换。
三、config.ini:使用配置文件,来灵活配置一些参数,修改起来也比较方便
四、getConfig.py:读取config.ini里的参数,方便后面调用
五、sendMail.py:封装发送邮件的方法,MIMEText添加附件
import os import smtplib import base64 from email.mime.text import MIMEText from email.mime.multipart import MIMEMultipart class SendEmail(object): def __init__(self, username, passwd, recv, title, content, file=None, ssl=False, email_host='smtp.126.com', port=25, ssl_port=465): self.username = username # 发送人邮箱 self.passwd = passwd # 发送人邮箱授权码 self.recv = recv # 收件人,多个要传list ['a@qq.com','b@qq.com] self.title = title # 邮件标题 self.content = content # 邮件正文 self.file = file # 附件路径,如果不在当前目录下,要写绝对路径 self.email_host = email_host # smtp服务器地址 self.port = port # 普通端口 self.ssl = ssl # 是否安全链接 self.ssl_port = ssl_port # 安全链接端口 def send_email(self): msg = MIMEMultipart() # 发送内容的对象 if self.file: # 处理附件的 file_name = os.path.split(self.file)[-1] # 只取文件名,不取路径 try: f = open(self.file, 'rb').read() except Exception as e: raise Exception('附件打不开') else: att = MIMEText(f, "base64", "utf-8") att["Content-Type"] = 'application/octet-stream' new_file_name = '=?utf-8?b?' + base64.b64encode(file_name.encode()).decode() + '?=' att["Content-Disposition"] = 'attachment; filename="%s"' % (new_file_name) msg.attach(att) msg.attach(MIMEText(self.content)) # 邮件正文的内容 msg['Subject'] = self.title # 邮件主题 msg['From'] = self.username # 发送者账号 msg['To'] = ','.join(self.recv) # 接收者账号列表 if self.ssl: self.smtp = smtplib.SMTP_SSL(self.email_host, port=self.ssl_port) else: self.smtp = smtplib.SMTP(self.email_host, port=self.port) # 发送邮件服务器的对象 self.smtp.login(self.username, self.passwd) try: self.smtp.sendmail(self.username, self.recv, msg.as_string()) pass except Exception as e: print('有bug~', e) else: print('发送成功!') self.smtp.quit()
六、用例场景准备
七、test1.py:封装测试接口,run~
import unittest import ddt import common.commons as c import common.sendMail as m import common.getConfig as cf from Base.Base_page import Base import os,json html_path = r'C:\Users\xxxxx\html' config = cf.ReadConfig() r = c.Common().ReadExcelTypeDict('sample.xlsx') # 拿到具体的Excel表数据 @ddt.ddt #导入ddt模块 class TestLogin(unittest.TestCase): @classmethod def setUpClass(cls) -> None: # setupclass类方法 全部用例开始前执行一次 cls.logs = c.Common().get_logs() # 导入日志方法 cls.logs.debug('开始写入接口自动化测试用例') @classmethod def tearDownClass(cls) -> None: cls.logs.debug('自动化接口用例结束') def setUp(self) -> None: self.logs.debug('开始本条接口用例') def tearDown(self) -> None: self.logs.debug('结束本条用例') @ddt.data(*r) # 引入ddt模块,读取拿到的数据 def test_select(self, pars): # 用例方法名开头必须是test_,pars参数为接收的表数据值,数据类型是str re_soap = pars['请求报文'] # 将Excel数据中的参数值转变为json格式 base_path = config.get_base_path('base_path') # url做切分,是为了方便不同测试环境 url = base_path + pars['URL'] # 拿到请求url rs_soap = pars['返回报文'] # 拿到预期结果 re_method = pars['re_method'] # 拿到请求方式 header = config.get_header('header') # 调用getConfig中的方法 result = Base().requests_type(method=re_method, url=url, data=re_soap, headers=json.loads(header)) # 请求接口 self.assertEqual(result.text, rs_soap) # 进行断言 看用例是否通过 if __name__ == '__main__': load = unittest.TestLoader().loadTestsFromTestCase(TestLogin) # loadTestsFromTestCase(类名)可以找到该类下所有test_开头的用例 suite = unittest.TestSuite([load, ]) c.Common().GetHtmlResult(suite, '测试用例') file_path = html_path + '\\' + os.listdir(html_path)[0] m.SendEmail( username=config.get_username('username'), passwd=config.get_passwd('passwd'), recv=config.get_recv('recv'), title=config.get_title('title'), content=config.get_content('content'), file=file_path, ssl=config.get_ssl('ssl') ).send_email()
至此~~ 主要流程就完成了~后面可以再优化一下,一些路径可以提取出来什么的。