使用Pytest生成HTML测试报告
背景
最近开发有关业务场景的功能时,涉及的API接口比较多,需要自己模拟多个业务场景的自动化测试(暂时不涉及性能测试),并且在每次测试完后能够生成一份测试报告。
考虑到日常使用Python自带的UnitTest,所以先从官方文档下手,了解到有相关的TestTextRunner:https://docs.python.org/zh-cn/3/library/unittest.html?highlight=unittest#unittest.TextTestRunner。
自带的TextTestRunner每次能把测试结果输出到流中的测试运行器,可以简单根据verbosity调整每次测试结果输出的信息,但是都太基础了,如果我想在测试过程中打印一些请求参数或者docstring,看了一下UnitTest内置的方法,实现过程可能会比较繁琐。
然后在网上找了一下轮子工具、html-testrunner、beautifulreport,这些工具生成的网页css、js都是使用公网的CDN,由于内网环境,不适合。
后面看了一些技术文章很多都是使用Pytest,之前有相关Pytest的基础使用经验,大概了解一下,决定根据Pytest+pytest-html满足当前测试场景。
模块安装
pip install pytest
pip install pytest-html
方案设计
pytest.ini
首先定义pytest.ini(pytest的基础配置文件,和测试文件在同一目录,使用pytest命令时会先读取该文件):
[pytest]
log_cli = True
log_cli_level = INFO
备注:开启日志消息打印,设置日志记录捕获的最低消息级别为INFO。
conftest.py
设置conftest.py(没有自己创建,同样是和测试文件同个目录下,用于pytest-html生成测试报告的配置文件):
# --*-- coding: utf-8 --*--
from datetime import datetime
from py.xml import html
import pytestdef pytest_html_report_title(report):report.title = "测试报告"def pytest_html_results_table_header(cells):cells.insert(2, html.th("Description"))cells.insert(1, html.th("Time", class_="sortable time", col="time"))cells.pop()def pytest_html_results_table_row(report, cells):cells.insert(2, html.td(report.description))def pytest_html_results_table_row(report, cells):cells.insert(2, html.td(report.description))cells.insert(1, html.td(datetime.utcnow(), class_="col-time"))cells.pop()@pytest.hookimpl(hookwrapper=True)
def pytest_runtest_makereport(item, call):outcome = yieldreport = outcome.get_result()report.description = str(item.function.__doc__)
通过设置钩子函数分别修改测试报告的列,添加描述列、测试用例耗时时间列、删除链接列,我这里是直接参考官方文档中给出的示例:https://pytest-html.readthedocs.io/en/latest/user_guide.html#creating-a-self-contained-report,有兴趣的可以研究一下。
测试用例
根据Pytest的官方文档,Pytest同样是支持UnitTest的功能,所以可以在原有的基础上直接运行Pytest:
# -*- coding: utf-8 -*-
# @Author: linshukai
# @Desc: pytestc测试用例
# @Date: 20220827import unittest
import pytest
import loggingimport requestsclass TestString(unittest.TestCase):def test_upper_method(self):"""测试字符串大写"""self.assertEqual("linshukai".upper(), "LINSHUKAI")logging.info("测试linshukai")def test_lower_method(self):"""测试字符串小写"""self.assertEqual( "ZhangSan".lower(), "zhangsan")logging.info("测试ZhangSan")def test_count_method(self):"""测试字符串长度统计"""self.assertEqual( len("zhangsan"), 8)logging.info("测试Zhangsan")class TestString2(unittest.TestCase):def test_get_html(self):"""测试请求网页状态码是否正常"""response = requests.get("http://www.baidu.com")self.assertEqual(response.status_code, 500)if __name__ == "__main__":pytest.main(["pytest_example.py", "--html=report.html", "--self
备注:简单写了几个测试用例,需要特别说明的是可以通过pytest.main()方法,直接在Python代码中调用Pytest,所以我每次只需要执行这个脚本就行,当然也可以选择在命令行界面通过Pytest命令调用指定测试文件执行指定测试用例。
另外一个地方需要注意的是–self-contained-html这个参数主要是针对pytest-html模块,由于默认pytest-html中生成测试报告的网页和CSS文件都是分开来存储的,如果想直接将css文件合并到html中,这样分享测试报告的时候也更加方便,所以只需要加入这个参数即可–self-contained-html。
预期效果
预期会出现的问题
Pytest中使用requests,抛出错误,但不影响测试结果,抛出的异常:
Windows fatal exception: code 1073807366
解决方式,降低Pytest为4.6.11版本后,异常就不会抛出,但是pytest-html需要6.0版本上的Pytest,由于不影响测试结果,更加完善的解决方法后续再研究。
【下面是我整理的2023年最全的软件测试工程师学习知识架构体系图】
一、Python编程入门到精通

二、接口自动化项目实战
三、Web自动化项目实战

四、App自动化项目实战
五、一线大厂简历

六、测试开发DevOps体系
七、常用自动化测试工具

八、JMeter性能测试
九、总结(尾部小惊喜)
生命不息,奋斗不止。每一份努力都不会被辜负,只要坚持不懈,终究会有回报。珍惜时间,追求梦想。不忘初心,砥砺前行。你的未来,由你掌握!
生命短暂,时间宝贵,我们无法预知未来会发生什么,但我们可以掌握当下。珍惜每一天,努力奋斗,让自己变得更加强大和优秀。坚定信念,执着追求,成功终将属于你!
只有不断地挑战自己,才能不断地超越自己。坚持追求梦想,勇敢前行,你就会发现奋斗的过程是如此美好而值得。相信自己,你一定可以做到!
相关文章:
使用Pytest生成HTML测试报告
背景 最近开发有关业务场景的功能时,涉及的API接口比较多,需要自己模拟多个业务场景的自动化测试(暂时不涉及性能测试),并且在每次测试完后能够生成一份测试报告。 考虑到日常使用Python自带的UnitTest,所…...
DSA之图(4):图的应用
文章目录 0 图的应用1 生成树1.1 无向图的生成树1.2 最小生成树1.2.1 构造最小生成树1.2.2 Prim算法构造最小生成树1.2.3 Kruskal算法构造最小生成树1.2.4 两种算法的比较 1.3 最短路径1.3.1 两点间最短路径1.3.2 某源点到其他各点最短路径1.3.3 Dijkstra1.3.4 Floyd 1.4 拓扑排…...
[SQL挖掘机] - 窗口函数 - row_number
介绍: row_number() 是一种常用的窗口函数,它为结果集中的每一行分配一个唯一的数字。这个数字的分配基于指定的排序顺序,并且不会跳过相同的排名。 用法: row_number() 函数的语法如下: row_number() over ([partition by 列名1, 列名2,…...
【论文阅读】通过解缠绕表示学习提升领域泛化能力用于主题感知的作文评分
摘要 本文工作聚焦于从领域泛化的视角提升AES模型的泛化能力,在该情况下,目标主题的数据在训练时不能被获得。本文提出了一个主题感知的神经AES模型(PANN)来抽取用于作文评分的综合的表示,包括主题无关(pr…...
二分查找P1873 [COCI2011-2012#5] EKO / 砍树
P1873 [COCI2011-2012#5] EKO / 砍树 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 这个题就是给新手练手的,在那个位置上在进行,寻找合适的砍树高度,下面在介绍一个二分查找的模板 int binarySearch(vector<int>& nums, int t…...
【BOOST程序库】正则表达式相关操作
基本概念这里不解释了,代码中详细解释了BOOST程序库中对于正则表达式常用方法的详细用法。 #include <iostream> #include <string>//正则表达式头文件 #include <boost/xpressive/xpressive.hpp>int main() {//声明正则:boost::pres…...
阿里云国际版在使用过程中应该注意什么呢?
为确保系统稳定性,用户不得进行以下操作。否则,阿里云可能无法解决由以下违规操作引起的问题: 1) Windows系统中的PV Drivers 程序不可删除 PV Drivers程序为服务器虚拟化驱动程序,请不要针对该程序进行任何操作,如果删…...
Flutter Provider 共享状态管理
在使用Provider的时候,我们主要关心三个概念: ChangeNotifier:真正数据(状态)存放的地方ChangeNotifierProvider:Widget树中提供数据(状态)的地方,会在其中创建对应的Ch…...
std vector 用法
使用vector,需添加头文件#include,要使用sort或find,则需要添加头文件#include。函数封装在命名空间std中,使用:using namespace std; 1、vector的初始化 std::vector<int> nVec; // 空对象 std::vecto…...
vue vite ts electron ipc addon-napi c arm64
初始化 因网络问题建议使用 cnpm 代替 npm npm init vue # 全选 yes npm i # 进入项目目录后使用 npm i electron electron-builder -D npm i commander -D # 额外组件electron 新建 plugins、src/electron 文件夹 添加 src/electron/background.ts 属于主进程 ipcMain.o…...
机器人科普--AGILOX 叉车
机器人科普--AGILOX 叉车 1 概述2 导航3 驱动轮组4 叉举参考 1 概述 AGILOX 叉车,不需要画地图路径,很厉害。 2 导航 中间路径自由导航,末端规划出轨迹路线,并使用优良的控制器做轨迹追踪。 AGILOX | 10 Min setu…...
Django的生命周期流程图(补充)、路由层urls.py文件、无名分组和有名分组、反向解析(无名反向解析、有名反向解析)、路由分发、伪静态
一、orm的增删改查方法(补充) 1. 查询resmodels.表名(类名).objects.all()[0]resmodels.表名(类名).objects.filter(usernameusername, passwordpassword).all()res models.表名(类名).objects.first() # 判断,判断数据是否有# res如果查询…...
selenium交互代码
一:selenium交互 用selenium打开网页后,也可以做一系列真人的操作,也就是利用selenium和浏览器进行交互,可利用以下几个函数进行操作: input.send_keys() 传递输入内容给某输入框button.click() 点击某按钮browser.e…...
下载远程服务器文件
业务需求:下载某云盘的视频文件存储到本地 测试代码 RequestMapping("testVideo")public String test() {try {SimpleDateFormat DATE_FORMAT new SimpleDateFormat("yyyy/MM/dd/");//组装本地保存地址StringBuilder filePath new StringBuilder(StoreP…...
[SQL挖掘机] - 索引
介绍: 当你在数据库中进行查询时,索引是一种用于提高查询性能的重要工具。索引是对表中的一列或多列进行排序的数据结构,它可以快速定位到满足特定条件的记录,从而减少了查询所需的时间和资源。 在数据库中使用索引的主要好处包括ÿ…...
C++STL库中的list
文章目录 list的介绍及使用 list的常用接口 list的模拟实现 list与vector的对比 一、list的介绍及使用 1. list是可以在常数范围内在任意位置进行插入和删除的序列式容器,并且该容器可以前后双向迭代。 2. list的底层是双向带头循环链表结构,双向带头循…...
【LeetCode 75】第十七题(1493)删掉一个元素以后全为1的最长子数组
目录 题目: 示例: 分析: 代码运行结果: 题目: 示例: 分析: 给一个数组,求删除一个元素以后能得到的连续的最长的全是1的子数组。 我们可以先单独统计出连续为1的子数组分别长度…...
配置IPv6 over IPv4 GRE隧道示例
组网需求 如图1,两个IPv6网络分别通过SwitchA和SwitchC与IPv4公网中的SwitchB连接,客户希望两个IPv6网络中的PC1和PC2实现互通。 其中PC1和PC2上分别指定SwitchA和SwitchC为自己的缺省网关。 图1 配置IPv6 over IPv4 GRE隧道组网图 配置思路 要实现I…...
Google Earth Engine谷歌地球引擎提取多波段长期反射率数据后绘制折线图并导出为Excel
本文介绍在谷歌地球引擎GEE中,提取多年遥感影像多个不同波段的反射率数据,在GEE内绘制各波段的长时间序列走势曲线图,并将各波段的反射率数据与其对应的成像日期一起导出为.csv文件的方法。 本文是谷歌地球引擎(Google Earth Engi…...
第三大的数
414、第三大的数 class Solution {public int thirdMax(int[] nums) {Arrays.sort(nums);int tempnums[0];int ansnums[0];int count 0;// if(nums.length<3){// return nums[nums.length-1];// }// else {for(int inums.length-1;i>0;i--){if (nums[i]>nums[i…...
云启出海,智联未来|阿里云网络「企业出海」系列客户沙龙上海站圆满落地
借阿里云中企出海大会的东风,以**「云启出海,智联未来|打造安全可靠的出海云网络引擎」为主题的阿里云企业出海客户沙龙云网络&安全专场于5.28日下午在上海顺利举办,现场吸引了来自携程、小红书、米哈游、哔哩哔哩、波克城市、…...
MFC内存泄露
1、泄露代码示例 void X::SetApplicationBtn() {CMFCRibbonApplicationButton* pBtn GetApplicationButton();// 获取 Ribbon Bar 指针// 创建自定义按钮CCustomRibbonAppButton* pCustomButton new CCustomRibbonAppButton();pCustomButton->SetImage(IDB_BITMAP_Jdp26)…...
理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端
🌟 什么是 MCP? 模型控制协议 (MCP) 是一种创新的协议,旨在无缝连接 AI 模型与应用程序。 MCP 是一个开源协议,它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。 可以把它想象成你的 AI 模型 和想要使用它…...
现代密码学 | 椭圆曲线密码学—附py代码
Elliptic Curve Cryptography 椭圆曲线密码学(ECC)是一种基于有限域上椭圆曲线数学特性的公钥加密技术。其核心原理涉及椭圆曲线的代数性质、离散对数问题以及有限域上的运算。 椭圆曲线密码学是多种数字签名算法的基础,例如椭圆曲线数字签…...
Spring Boot+Neo4j知识图谱实战:3步搭建智能关系网络!
一、引言 在数据驱动的背景下,知识图谱凭借其高效的信息组织能力,正逐步成为各行业应用的关键技术。本文聚焦 Spring Boot与Neo4j图数据库的技术结合,探讨知识图谱开发的实现细节,帮助读者掌握该技术栈在实际项目中的落地方法。 …...
全志A40i android7.1 调试信息打印串口由uart0改为uart3
一,概述 1. 目的 将调试信息打印串口由uart0改为uart3。 2. 版本信息 Uboot版本:2014.07; Kernel版本:Linux-3.10; 二,Uboot 1. sys_config.fex改动 使能uart3(TX:PH00 RX:PH01),并让boo…...
Spring数据访问模块设计
前面我们已经完成了IoC和web模块的设计,聪明的码友立马就知道了,该到数据访问模块了,要不就这俩玩个6啊,查库势在必行,至此,它来了。 一、核心设计理念 1、痛点在哪 应用离不开数据(数据库、No…...
Unity | AmplifyShaderEditor插件基础(第七集:平面波动shader)
目录 一、👋🏻前言 二、😈sinx波动的基本原理 三、😈波动起来 1.sinx节点介绍 2.vertexPosition 3.集成Vector3 a.节点Append b.连起来 4.波动起来 a.波动的原理 b.时间节点 c.sinx的处理 四、🌊波动优化…...
代理篇12|深入理解 Vite中的Proxy接口代理配置
在前端开发中,常常会遇到 跨域请求接口 的情况。为了解决这个问题,Vite 和 Webpack 都提供了 proxy 代理功能,用于将本地开发请求转发到后端服务器。 什么是代理(proxy)? 代理是在开发过程中,前端项目通过开发服务器,将指定的请求“转发”到真实的后端服务器,从而绕…...
JAVA后端开发——多租户
数据隔离是多租户系统中的核心概念,确保一个租户(在这个系统中可能是一个公司或一个独立的客户)的数据对其他租户是不可见的。在 RuoYi 框架(您当前项目所使用的基础框架)中,这通常是通过在数据表中增加一个…...



