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日志并进行多维度分析。
目录
相关文章
|
9天前
|
机器学习/深度学习 数据采集 TensorFlow
使用Python实现智能食品加工优化的深度学习模型
使用Python实现智能食品加工优化的深度学习模型
103 59
|
1月前
|
Web App开发 前端开发 JavaScript
探索Python科学计算的边界:利用Selenium进行Web应用性能测试与优化
【10月更文挑战第6天】随着互联网技术的发展,Web应用程序已经成为人们日常生活和工作中不可或缺的一部分。这些应用不仅需要提供丰富的功能,还必须具备良好的性能表现以保证用户体验。性能测试是确保Web应用能够快速响应用户请求并处理大量并发访问的关键步骤之一。本文将探讨如何使用Python结合Selenium来进行Web应用的性能测试,并通过实际代码示例展示如何识别瓶颈及优化应用。
99 5
|
1月前
|
数据采集 存储 JavaScript
自动化数据处理:使用Selenium与Excel打造的数据爬取管道
本文介绍了一种使用Selenium和Excel结合代理IP技术从WIPO品牌数据库(branddb.wipo.int)自动化爬取专利信息的方法。通过Selenium模拟用户操作,处理JavaScript动态加载页面,利用代理IP避免IP封禁,确保数据爬取稳定性和隐私性。爬取的数据将存储在Excel中,便于后续分析。此外,文章还详细介绍了Selenium的基本设置、代理IP配置及使用技巧,并探讨了未来可能采用的更多防反爬策略,以提升爬虫效率和稳定性。
|
10天前
|
Java 测试技术 持续交付
【入门思路】基于Python+Unittest+Appium+Excel+BeautifulReport的App/移动端UI自动化测试框架搭建思路
本文重点讲解如何搭建App自动化测试框架的思路,而非完整源码。主要内容包括实现目的、框架设计、环境依赖和框架的主要组成部分。适用于初学者,旨在帮助其快速掌握App自动化测试的基本技能。文中详细介绍了从需求分析到技术栈选择,再到具体模块的封装与实现,包括登录、截图、日志、测试报告和邮件服务等。同时提供了运行效果的展示,便于理解和实践。
45 4
【入门思路】基于Python+Unittest+Appium+Excel+BeautifulReport的App/移动端UI自动化测试框架搭建思路
|
5天前
|
机器学习/深度学习 算法 数据可视化
使用Python实现深度学习模型:智能食品配送优化
使用Python实现深度学习模型:智能食品配送优化
21 2
|
9天前
|
搜索推荐 Python
快速排序的 Python 实践:从原理到优化,打造你的排序利器!
本文介绍了 Python 中的快速排序算法,从基本原理、实现代码到优化方法进行了详细探讨。快速排序采用分治策略,通过选择基准元素将数组分为两部分,递归排序。文章还对比了快速排序与冒泡排序的性能,展示了优化前后快速排序的差异。通过这些分析,帮助读者理解快速排序的优势及优化的重要性,从而在实际应用中选择合适的排序算法和优化策略,提升程序性能。
23 1
|
14天前
|
运维 监控 Linux
自动化运维:如何利用Python脚本优化日常任务##
【10月更文挑战第29天】在现代IT运维中,自动化已成为提升效率、减少人为错误的关键技术。本文将介绍如何通过Python脚本来简化和自动化日常的运维任务,从而让运维人员能够专注于更高层次的工作。从备份管理到系统监控,再到日志分析,我们将一步步展示如何编写实用的Python脚本来处理这些任务。 ##
|
1月前
|
测试技术 Python
自动化测试项目学习笔记(一):unittest简单运行(初始化,清除,设置测试行为)
本文介绍了Python的unittest框架的基础用法,包括测试初始化(setup)、清除(tearDown)函数的使用,以及assertEqual和assertGreaterEqual等断言方法,并展示了如何创建测试用例,强调了测试函数需以test_开头才能被运行。
62 1
自动化测试项目学习笔记(一):unittest简单运行(初始化,清除,设置测试行为)
|
29天前
|
XML 前端开发 数据格式
Beautiful Soup 解析html | python小知识
在数据驱动的时代,网页数据是非常宝贵的资源。很多时候我们需要从网页上提取数据,进行分析和处理。Beautiful Soup 是一个非常流行的 Python 库,可以帮助我们轻松地解析和提取网页中的数据。本文将详细介绍 Beautiful Soup 的基础知识和常用操作,帮助初学者快速入门和精通这一强大的工具。【10月更文挑战第11天】
56 2
|
1月前
|
SQL 关系型数据库 数据库
优化Web开发流程:Python ORM的优势与实现细节
【10月更文挑战第4天】在Web开发中,数据库操作至关重要,但直接编写SQL语句既繁琐又易错。对象关系映射(ORM)技术应运而生,让开发者以面向对象的方式操作数据库,显著提升了开发效率和代码可维护性。本文探讨Python ORM的优势及其实现细节,并通过Django ORM的示例展示其应用。ORM提供高级抽象层,简化数据库操作,提高代码可读性,并支持多种数据库后端,防止SQL注入。Django内置强大的ORM系统,通过定义模型、生成数据库表、插入和查询数据等步骤,展示了如何利用ORM简化复杂的数据库操作。
59 6