python3 unittest+BeautifulReport单个进程输出多个测试报告

最近一个项目中需要由于输出的案例内容非常多(上万条),导致BeautifulReport输出的报告内容非常大(几百兆)。浏览器无法正常处理这么大的测试报告,就算打开了,也不方便阅读和处理,因此需要将报告分成多个输出。

经修改代码,发现单个进程内输出多个测试报告出现问题:第一个测试报告能正常数据对应加入到unittest.testSuite的中的案例,但是后面每一个报告会输出前面所有报告的案例。

如果进行多进程改造的话改造量又比较大,因此还是采用的单进程多线程方案。

经排查发现是BeautifulReport中用于存放测试结果的变量FIELDS是一个全局变量,因此就算新建多个BeautifulReport的实例也没办法正常输出每个实例中unittest.testSuite的报告内容,需修改BeautifulReport中关于FIELDS变量的使用。

结合unittest和BeautifulReport测试api接口的的使用代码如下:

 1 #!/usr/bin/python
 2 import os,sys
 3 from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor, as_completed
 4 from multiprocessing import Process, Lock, Queue
 5 import unittest
 6 import time
 7 import  copy
 8 sys.path.append(r'')
 9 
10 from BeautifulReport import BeautifulReport
11 
12 def output_report(testsuit, filename, interface_name):
13     try:
14         log.info(f"output_report filename:{filename} interface_name:{interface_name}")
15         now = time.strftime("%Y-%m-%d_%H_%M_%S")
16         result = BeautifulReport(testsuit)
17         result.report(filename=now + "_" + filename + f"_{interface_name}" +'_测试报告.html', description='测试报告', log_path='../report')
18 
19         log.info(f"output_report filename:{filename} interface_name:{interface_name} over")
20         print(f"******output_report filename:{filename} interface_name:{interface_name} over******")
21 
22         return {'result':True}
23     except Exception as e:
24         print(f"output_report filename:{filename} interface_name:{interface_name} exception! error_info:{e}")
25         return {'result':False, 'interface_name':interface_name, 'error_info':e}
26 
27 def demo_run(cases):
28     #省略一些准备代码
29     #......
30     
31     #多线程执行api接口测试任务
32     with ThreadPoolExecutor(max_workers=thread_num) as ts:
33         for case in cases:
34             if len(case['req']) == 1 and len(case['file_rsp']) != 1:
35                 log.error(f"case_id:{case['TestCaseID']} file_rsp len:{len(case['file_rsp'])} != 1 error!")
36                 continue
37             task.append(ts.submit(test.send_request, api, case))
38 
39     #收集任务返回结果
40     result_msg_list = [future.result() for future in as_completed(task)]
41 
42     #将执行结果加入到testsuit中
43     #todo:输出报告如果太大内容太多导致输出时间长,则需要改造为多线程处理
44     test_suit_dict = {}
45     result_msg_list.sort(key=lambda x:x["TestCaseID"])
46     for result_msg in result_msg_list:
47         interface_name = result_msg['interface_name']
48         log.info(f"TestCaseID:{result_msg['TestCaseID']} interface_name:{interface_name} func_name:{result_msg['func_name']}")
49 
50         if interface_name in test_suit_dict:
51             testsuit = test_suit_dict[interface_name]
52             testsuit.addTest(ParametrizedTestCase.parametrize(Test_Cash_Order_Api, "test_case_ATP", param=(result_msg,key)))
53         else:
54             testsuit = unittest.TestSuite()
55             test_suit_dict[interface_name] = testsuit
56             testsuit.addTest(ParametrizedTestCase.parametrize(Test_Cash_Order_Api, "test_case_ATP", param=(result_msg,key)))
57 
58     #检查输出报告目录是否存在
59     if os.path.exists("../report") != True:
60         os.makedirs("../report")
61 
62     #BeautifulReport输出testsuit中的比对结果
63     #注意这里输出多个测试报告需改造Beautifulreport源码中存放测试结果的FIELDS的使用,否则无法正常输出多个测试报告(每个测试报告会输出前面加入的测试集的结果)
64     #因为Beautifulreport源码中用的FIELDS变量是个全局变量,单个进程中加入到FIELDS中的测试结果会不断累计。需要将FIELDS变为类的成员变量。这样新建多个BeautifulReport的实例才能正常输出多个测试报告
65     #另外使用多进程输出多个测试报告比较难实现。需要多进程中使用功能的内容都是进程安全的,涉及到的logging等组件的使用都需要做改造。这里直接改造Beautifulreport中的FIELDS较为容易实现
66     for interface_name, testsuit in test_suit_dict.items():
67         log.info(f"add process filename:{filename} interface_name:{interface_name}")
68         output_report(testsuit, filename, interface_name)

 

BeautifulReport中改造FIELDS的代码如下。左侧为改造前代码,右侧为改造后代码。思路是将FIELDS变为类的成员变量,而不是使用全局变量。

基类中初始化FIELDS为类成员变量:

输出的报告内容使用成员变量存储:

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/774445.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

windows11解决visual c++6.0 打开提示不兼容弹窗问题

在Windows11系统中,打开Visual C++ 6.0 编辑器,会弹出不兼容弹窗,如图所示下面将给出解决办法,实测有效。 步骤1:重命名MSDEV.EXE文件 步骤2:修改“兼容模式”配置 步骤3:修改“目标”输入框内容 步骤4:重新启动软件人生如逆旅 我亦是行人

零基础快速上手STM32开发(手把手保姆级教程)

1 前言 作为一名嵌入式工程师,STM32 是必须要学习的一款单片机,同时这款单片机资料足够多,而且比较简单,非常适合初学者入门。 STM32 是一款由 STMicroelectronics 公司开发的 32 位微控制器,由于其强大的处理能力和广泛的应用领域,如嵌入式系统、物联网设备、机器人等,…

比网盘、FTP更好用的数据摆渡工具是什么?

企业进行网络隔离后,数据在隔离网间交换时就产生了数据摆渡需求,常见的数据摆渡工具包括移动U盘、网盘、FTP等,企业通常选择网盘、FTP来进行日常的数据摆渡操作。但网盘和FTP在数据摆渡上均存在不同程度的缺陷,具体表现在: 数据量限制:网盘一般面向办公文档型数据,系统往…

全文检索方案

1. 方案概述 本文旨在设计全文搜索功能,包括数据的存储、数据权限、数据接口、数据模型等,从整体设计全文检索方案。 2. 解决方案 全文搜索解决方案主要包含两部分,数据的存储及数据的查询展示,其中数据存储方面,主要分为业务数据存储及附件存储;而数据查询展示主…

课堂笔记 - C++ 位运算符

C++位运算符 在C++当中,有六个位操作运算符,二进制来进行操作 & 按位与 1 & 0 = 0 | 按位或 1 | 0 = 1 ~ 按位非 0 取反变成 1 1取反变成0 ^ 异或 相同为0 不同为1 << 左移 二进制往左靠,右侧补零 >> 右移 二进制往右靠,左侧补零 0xff = 很明…

netty核心流程(二):客户端与服务端的读写过程

连接成功建立后,客户端是如何向服务端发送请求的? 由于内部源码的调用过于复杂,我们只分析有代表性的代码。在 AbstractChannel 类中我们可以看到: wirte() 方法最后会把发送的数据 msg 放入 addMessage() 方法中,这个方法是做什么的呢? 原来把要发送数据放入一个缓冲链…

P1168 中位数题解

题目链接:https://www.luogu.com.cn/problem/P1168 题目描述:给定一个长度为 N 的非负整数序列 A,对于前奇数项求中位数。 思路讲解:最简单的想法就是每次取我们要的那段数组然后排序在输出中位数。确实可以,但是太慢了,直接超时。那就是说要缩短时间,那就可以直接用到堆…

Qt/C++音视频开发80-ffmpeg实现srt推拉流/实时性非常好/音视频同步/支持格式众多

一、前言 目前互联网上的视频直播有两种,一种是基于RTMP协议的直播,这种直播方式上行推流使用RTMP协议,下行播放使用RTMP,HTTP+FLV或者HLS,直播延时一般大于3秒,广泛应用秀场、游戏、赛事和事件直播,满足了对交互要求不高的场景;另一种是WebRTC协议的直播,这种直播方式…

一款基于Fluent设计风格、现代化的WPF UI控件库

前言 今天大姚给大家分享一款基于Fluent设计风格、开源(MIT License)、现代化的WPF UI控件库,它提供直观的设计、主题、导航和全新的沉浸式控件,全部都是原生且无缝地集成在一起:WPF UI。WPF介绍 WPF 是一个强大的桌面应用程序框架,用于构建具有丰富用户界面的 Windows 应…

很幸运,AppStore审核一遍过!——深海记词

极速过审 从2023年9月开始学习iOS开发,终于在24年6月正式开发完成了第一款用于学英语、背单词的APP《深海记词》。 最近在上海出差,闲暇之余开始着手制作商店页海报,做完后就急不可耐的提交了审核。 我是在周六晚上提交的审核,周天早上显示受理审核,下午就显示通过了审核�…

异或哈希

理论基础异或哈希是个很神奇的算法,利用了异或操作的特殊性和哈希降低冲突的原理,可以用于快速找到一个组合是否出现、序列中的数是否出现了k次https://blog.csdn.net/notonlysuccess/article/details/130959107 https://codeforces.com/blog/entry/85900 CF1175Fhttps://cod…