python+requests+excel+unittest+ddt接口自动化数据驱动并生成html报告(优化版)

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: python+requests+excel+unittest+ddt接口自动化数据驱动并生成html报告(优化版)

本文章内容是基于上海-悠悠的版本,进行了优化,增加了部分内容,详细请查阅下文。

1、原文链接

python+requests+excel+unittest+ddt接口自动化数据驱动并生成html报告

2、修改前后框架区别

修改前:
在这里插入图片描述
修改后:
在这里插入图片描述

3、主要修改内容

  • 增加:token关联(token获取和保存)
  • 增加:cookie关联(cookie获取和保存)
  • 增加:发送邮件(使用SMTP)
  • 修改:HTML报告模板中的样式和ddt用例的标题
  • 增加:logo日志

### 4、详细修改内容说明
#### 4.1、增加token关联
##### 4.1.1、token获取get_token.py

import json
import requests
from common.operation_json import OperetionJson

class OperationHeader:

    def __init__(self, response):
        # self.response = json.loads(response)
        self.response = response

    def get_response_token(self):
        '''
        获取登录返回的token
        '''
        token = {"data":{"token":self.response['data']['token']}}
        #token = {"token": self.response['data']['token']}
        return token

    def write_token(self):
        op_json = OperetionJson()
        op_json.write_data(self.get_response_token())

    def get_response_msg(self):
        reponse_msg = {"msg":self.response['msg']}
        #print("reponse_msg:", reponse_msg)
        return reponse_msg
4.1.2、token保存operation_json.py
#coding:utf-8
import json
class OperetionJson:

    def __init__(self,file_path=None):
        if file_path  == None:
            self.file_path = '../case/cookie.json'
        else:
            self.file_path = file_path
        self.data = self.read_data()

    #读取json文件
    def read_data(self):
        with open(self.file_path, 'r', encoding='utf-8') as fp:
            data1 = fp.read()
            if len(data1) > 0:
                data = json.loads(data1)
            else:
                data = {}
            return data

    #根据关键字获取数据
    def get_data(self,id):
        print(type(self.data))
        return self.data[id]

    #写json
    def write_data(self,data):
        with open('../case/token.json','w') as fp:
            fp.truncate()  # 先清空之前的数据,再写入,这样每次登录的token都是不一样的
            fp.write(json.dumps(data))
4.1.3、token的读取base_api.py

在原代码中加入token的读取,即把token加入到heasers中

 # 请求头部headers
    try:
        headers = eval(testdata["headers"])
        if testdata["token"] == "yes":
            op_json = OperetionJson("../case/token.json")
            token = op_json.get_data('data')
            headers = dict(headers, **token)
        print("请求头部:", headers)
        log.info("请求头部:", headers)
    except:
        headers = None

4.2、增加cookie关联

实现逻辑和获取token一模一样

4.2.1、cookie获取get_token.py

直接在获取token的get_token.py中加入,而这里的token格式需要根据自己的业务修改

    def get_response_cookie(self):
        cookie1 = requests.utils.dict_from_cookiejar(self.response.cookies)
        cookie = {"data":{"gfsessionid":cookie1["gfsessionid"]}}
        # {"data": {"token": self.response['data']['token']}}
        print("cookie:", cookie)
        return cookie
    def write_cookie(self):
        op = OperetionJson()
        op.write_mydata(self.get_response_cookie())
4.2.2、cookie保存operation_json.py

直接在operation_json.py中加入

    def write_mydata(self,data):
        with open('../case/cookie.json','w') as fp:
            fp.truncate()  # 先清空之前的数据,再写入,这样每次登录的token都是不一样的
            fp.write(json.dumps(data))
4.2.3、cookie的读取base_api.py

直接在base_api.py中加入

    try:
        headers = eval(testdata["headers"])
        if testdata["cookie"] == "yes":
            op_json = OperetionJson("../case/cookie.json")
            token1 = op_json.get_data('data')
            headers = dict(headers, **token1)
        print("请求头部:", headers)
        log.info("请求头部:", headers)
    except:
        headers = None

4.3、增加邮件服务

4.3.1、邮件服务封装send_mail.py
#coding=utf-8
from email.mime.text import MIMEText
import time
import smtplib
import getpass
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email import encoders
import email
import os

def sendmain(file_path,mail_to = 'xxxxx@126.com'):
    mail_from = 'yyyyy@126.com'
    f = open(file_path,'rb')
    mail_body=f.read()
    f.close()
    
    #msg = email.MIMEMultipart.MIMEMultipart()
    msg = MIMEMultipart()

    # 构造MIMEBase对象做为文件附件内容并附加到根容器  
    contype = 'application/octet-stream'  
    maintype, subtype = contype.split('/', 1)  
    ## 读入文件内容并格式化  
    data = open(file_path, 'rb')
    #file_msg = email.MIMEBase.MIMEBase(maintype, subtype)
    file_msg = MIMEBase(maintype, subtype)
    file_msg.set_payload(data.read( ))  
    data.close( )  
    #email.Encoders.encode_base64(file_msg)
    encoders.encode_base64(file_msg)
    ## 设置附件头  
    basename = os.path.basename(file_path)  
    file_msg.add_header('Content-Disposition',  
                        'attachment', filename = basename)  
    msg.attach(file_msg)  
    print(u'msg 附件添加成功')
    
    msg1 = MIMEText(mail_body,_subtype='html',_charset='utf-8')
    msg.attach(msg1)
    
    if isinstance(mail_to,str):
        msg['To'] = mail_to
    else: 
        msg['To'] = ','.join(mail_to)
    msg['From'] = mail_from
    msg['Subject'] = u'xxxxxxxxx接口自动化测试' # 邮件标题
    msg['date']=time.strftime('%Y-%m-%d-%H_%M_%S')
    print(msg['date'])

    smtp = smtplib.SMTP()
    smtp.connect('smtp.126.com')
    smtp.login('yyyyyy@126.com','aaaaaaaaaa') # 这里的密码是邮件第三方客户端认证密码
    smtp.sendmail(mail_from, mail_to, msg.as_string())
    smtp.quit()
    print('email has send out !')
'''
if __name__=='__main__':
    sendmain('../report/2017-08-18-10_18_57_result.html')
'''
4.3.2、邮件调用run_this.py

直接在主函数入口中调用

sendmain(htmlreport, mail_to=['hhhhhhhh@126.com', 'jjjjjj@126.com', 'uuuuuu@126.com']) #多个收件人的话,直接在列表中,用,号隔开即可

4.4、修改html报告模板

4.4.1、修改报告中用例的标题,修改ddt源码

①原报告用例的标题:
因为使用ddt,所以ddt格式中用例标题是test_api_数字开头的用例名称,如果要自定义需要修改ddt源码

在这里插入图片描述
②修改后的报告标题:
在这里插入图片描述
③ 如何修改?
可以参考之前的博文:
unittest中使用ddt后生成的测试报告名称如何修改?(如test_api_0修改成test_api_0_titile)

def mk_test_name(name, value, index=0):
    """
    Generate a new name for a test case.

    It will take the original test name and append an ordinal index and a
    string representation of the value, and convert the result into a valid
    python identifier by replacing extraneous characters with ``_``.

    We avoid doing str(value) if dealing with non-trivial values.
    The problem is possible different names with different runs, e.g.
    different order of dictionary keys (see PYTHONHASHSEED) or dealing
    with mock objects.
    Trivial scalar values are passed as is.

    A "trivial" value is a plain scalar, or a tuple or list consisting
    only of trivial values.
    """

    # Add zeros before index to keep order

    index = "{0:0{1}}".format(index + 1, index_len, )
    if not is_trivial(value) and type(value) is not dict: # 增加的地方,增加value的字典判断

        return "{0}_{1}_{2}".format(name, index, value.name) # 修改的地方,增加返回的值
    if type(value) is dict: # 增加的地方
        try: # 增加的地方
            value = value["name"] + "_" + value["function"] # 增加的地方,name和function必须是execl用例中整正存在的表头,这里我是把两个表头合并了(name是我表格中接口的名称,function是表格中接口的功能描述)
        except: # 增加的地方
            return "{0}_{1}".format(name.index) # 增加的地方
    try:
        value = str(value)
    except UnicodeEncodeError:
        # fallback for python2
        value = value.encode('ascii', 'backslashreplace')
    test_name = "{0}_{1}_{2}".format(name, index, value)  # 修改的地方
    return re.sub(r'\W|^(?=\d)', '_', test_name)
4.4.2、增加用例执行人

在HTMLTestRunner.py中加入如下,即获取当前用例执行的负载机的用户名

 DEFAULT_TESTER = getpass.getuser()

4.5、增加log日志

4.5.1、在框架入口中直接加入run_this.py
# LOG日志记录
    logging.basicConfig(level=logging.DEBUG,
                        format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',
                        datefmt='%a, %d %b %Y %H:%M:%S',
                        filename=log_path + '/' + now + r"result.log",
                        filemode='w')
    logger = logging.getLogger()
    logger.info(all_case)

详细可以参考之前的博文:
Unittest接口测试生成报告和日志方法

4.5.2、在其它模块中直接使用即可
log = logging.getLogger()
log.info("请求头部:", headers)

5、其它截图

log截图:
在这里插入图片描述
测试报告:

在这里插入图片描述
邮件:
在这里插入图片描述

相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
目录
相关文章
|
10天前
|
Java 测试技术 持续交付
【入门思路】基于Python+Unittest+Appium+Excel+BeautifulReport的App/移动端UI自动化测试框架搭建思路
本文重点讲解如何搭建App自动化测试框架的思路,而非完整源码。主要内容包括实现目的、框架设计、环境依赖和框架的主要组成部分。适用于初学者,旨在帮助其快速掌握App自动化测试的基本技能。文中详细介绍了从需求分析到技术栈选择,再到具体模块的封装与实现,包括登录、截图、日志、测试报告和邮件服务等。同时提供了运行效果的展示,便于理解和实践。
44 4
【入门思路】基于Python+Unittest+Appium+Excel+BeautifulReport的App/移动端UI自动化测试框架搭建思路
|
5天前
|
存储 Python
Python自动化脚本编写指南
【10月更文挑战第38天】本文旨在为初学者提供一条清晰的路径,通过Python实现日常任务的自动化。我们将从基础语法讲起,逐步引导读者理解如何将代码块组合成有效脚本,并探讨常见错误及调试技巧。文章不仅涉及理论知识,还包括实际案例分析,帮助读者快速入门并提升编程能力。
23 2
|
7天前
|
运维 监控 Python
自动化运维:使用Python脚本简化日常任务
【10月更文挑战第36天】在数字化时代,运维工作的效率和准确性成为企业竞争力的关键。本文将介绍如何通过编写Python脚本来自动化日常的运维任务,不仅提高工作效率,还能降低人为错误的风险。从基础的文件操作到进阶的网络管理,我们将一步步展示Python在自动化运维中的应用,并分享实用的代码示例,帮助读者快速掌握自动化运维的核心技能。
19 3
|
5天前
|
数据采集 IDE 测试技术
Python实现自动化办公:从基础到实践###
【10月更文挑战第21天】 本文将探讨如何利用Python编程语言实现自动化办公,从基础概念到实际操作,涵盖常用库、脚本编写技巧及实战案例。通过本文,读者将掌握使用Python提升工作效率的方法,减少重复性劳动,提高工作质量。 ###
20 1
|
9天前
|
图形学 Python
SciPy 空间数据2
凸包(Convex Hull)是计算几何中的概念,指包含给定点集的所有凸集的交集。可以通过 `ConvexHull()` 方法创建凸包。示例代码展示了如何使用 `scipy` 库和 `matplotlib` 绘制给定点集的凸包。
19 1
|
10天前
|
JSON 数据格式 索引
Python中序列化/反序列化JSON格式的数据
【11月更文挑战第4天】本文介绍了 Python 中使用 `json` 模块进行序列化和反序列化的操作。序列化是指将 Python 对象(如字典、列表)转换为 JSON 字符串,主要使用 `json.dumps` 方法。示例包括基本的字典和列表序列化,以及自定义类的序列化。反序列化则是将 JSON 字符串转换回 Python 对象,使用 `json.loads` 方法。文中还提供了具体的代码示例,展示了如何处理不同类型的 Python 对象。
|
11天前
|
数据采集 Web App开发 iOS开发
如何使用 Python 语言的正则表达式进行网页数据的爬取?
使用 Python 进行网页数据爬取的步骤包括:1. 安装必要库(requests、re、bs4);2. 发送 HTTP 请求获取网页内容;3. 使用正则表达式提取数据;4. 数据清洗和处理;5. 循环遍历多个页面。通过这些步骤,可以高效地从网页中提取所需信息。
|
9天前
|
索引 Python
SciPy 空间数据1
SciPy 通过 `scipy.spatial` 模块处理空间数据,如判断点是否在边界内、计算最近点等。三角测量是通过测量角度来确定目标距离的方法。多边形的三角测量可将其分解为多个三角形,用于计算面积。Delaunay 三角剖分是一种常用方法,可以对一系列点进行三角剖分。示例代码展示了如何使用 `Delaunay()` 函数创建三角形并绘制。
19 0
|
11天前
|
Web App开发 测试技术 数据安全/隐私保护
自动化测试的魔法:使用Python进行Web应用测试
【10月更文挑战第32天】本文将带你走进自动化测试的世界,通过Python和Selenium库的力量,展示如何轻松对Web应用进行自动化测试。我们将一起探索编写简单而强大的测试脚本的秘诀,并理解如何利用这些脚本来确保我们的软件质量。无论你是测试新手还是希望提升自动化测试技能的开发者,这篇文章都将为你打开一扇门,让你看到自动化测试不仅可行,而且充满乐趣。
|
1月前
|
机器学习/深度学习 人工智能 运维
构建高效运维体系:从自动化到智能化的演进
本文探讨了如何通过自动化和智能化手段,提升IT运维效率与质量。首先介绍了自动化在简化操作、减少错误中的作用;然后阐述了智能化技术如AI在预测故障、优化资源中的应用;最后讨论了如何构建一个既自动化又智能的运维体系,以实现高效、稳定和安全的IT环境。
64 4

热门文章

最新文章