【Pytest官方文档翻译及学习】2.2 如何在测试中编写和报告断言

目录

2.2 如何在测试中编写和报告断言

2.2.1 使用assert语句断言

2.2.2 关于预期异常的断言

2.2.3 关于预期警告的断言

2.2.4 应用上下文相关的比较

2.2.5 为失败的断言定义自己的解释

2.2.6 断言内省细节


2.2 如何在测试中编写和报告断言

2.2.1 使用assert语句断言

pytest允许您使用标准的Python断言来验证Python测试中的期望值和值。例如,您可以编写以下内容:

# content of test_assert1.py 
def f(): return 3 
def test_function(): assert f() == 4

断言您的函数返回某个值。如果此断言失败,您将看到函数调用的返回值:

$ pytest test_assert1.py
=========================== test session starts ============================
platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y
rootdir: /home/sweet/project
collected 1 item
test_assert1.py F [100%]
================================= FAILURES =================================test_function _
def test_function():assert f() == 4
E assert 3 == 4
E + where 3 = f()
test_assert1.py:6: AssertionError
========================= short test summary info ==========================
FAILED test_assert1.py::test_function - assert 3 == 4
============================ 1 failed in 0.12s =============================

pytest支持显示最常见的子表达式的值,包括调用、属性、比较以及二进制和一元运算符。(请参阅使用pytest演示Python故障报告Demo of Python failure reports with pytest)。这允许您在不丢失内省信息的情况下使用惯用的python构造,而不需要样板代码。

但是,如果您指定一条消息,并使用以下断言:

assert a % 2 == 0, "value was odd, should be even"

那么根本不进行断言内省,消息将简单地显示在回溯中。

有关断言内省的更多信息,请参阅Assertion introspection details

2.2.2 关于预期异常的断言

为了编写关于引发异常的断言,可以使用pytest.reses()作为上下文管理器,如下所示:

import pytest 
def test_zero_division(): with pytest.raises(ZeroDivisionError): 1 / 0

如果您需要访问实际的异常信息,您可以使用:

def test_recursion_depth(): with pytest.raises(RuntimeError) as excinfo: def f(): f() f() assert "maximum recursion" in str(excinfo.value)

excinfo是一个ExceptionInfo实例,它是引发实际异常的包装器。感兴趣的主要属性是.type、.value和.traceback。

您可以将match关键字参数传递给上下文管理器,以测试正则表达式在异常的字符串表示形式上是否匹配(类似于unittest中的TestCase.assertRailesRegex方法):

import pytest def myfunc(): raise ValueError("Exception 123 raised") def test_match(): with pytest.raises(ValueError, match=r".* 123 .*"): myfunc()

match方法的regexp参数与re.search函数匹配,因此在上面的示例中,match='123'也会起作用。

pytest.raises()函数的另一种形式是,您可以传递一个将使用给定的*args和**kwargs执行的函数,并断言引发了给定的异常:

pytest.raises(ExpectedException, func, *args, **kwargs)

在出现诸如无异常或错误异常之类的故障时,报告器将为您提供有用的输出。

请注意,也可以为pytest.mark.xfail指定一个“raises”参数,该参数检查测试是否以引发任何异常更具体的方式失败:

@pytest.mark.xfail(raises=IndexError) 
def test_f(): f()

使用pytest.reises()可能更适合于测试自己的代码故意引发的异常的情况,而使用带有check函数的@pytest.mark.xfail可能更适合记录未修复的错误(测试描述了“应该”发生什么)或依赖关系中的错误。

2.2.3 关于预期警告的断言

您可以使用pytest.warns检查代码是否引发特定警告。

2.2.4 应用上下文相关的比较

pytest对在遇到比较时提供上下文相关的信息提供了丰富的支持。例如:

# content of test_assert2.py 
def test_set_comparison(): set1 = set("1308") set2 = set("8035") assert set1 == set2

如果运行此模块:

$ pytest test_assert2.py 
=========================== test session starts ============================ 
platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y 
rootdir: /home/sweet/project 
collected 1 item 
test_assert2.py F [100%] 
================================= FAILURES ================================= 
___________________________ test_set_comparison ____________________________ 
def test_set_comparison(): 
set1 = set("1308") 
set2 = set("8035") 
> assert set1 == set2 
E AssertionError: assert {'0', '1', '3', '8'} == {'0', '3', '5', '8'} 
E Extra items in the left set: 
E '1' 
E Extra items in the right set: 
E '5' 
E Use -v to get more diff 
test_assert2.py:4: AssertionError 
========================= short test summary info ========================== 
FAILED test_assert2.py::test_set_comparison - AssertionError: assert {'0'... 
============================ 1 failed in 0.12s =============================

对一些情况进行了特别比较:

  • 比较长字符串:显示上下文差异
  • 比较长序列:首次失败指数
  • 比较dicts:不同条目

有关更多示例,请参阅reporting demo

2.2.5 为失败的断言定义自己的解释

可以通过实现pytest_asserrepr_compare来添加您自己的详细解释。

pytest_asserrepr_compareconfig, op, left, right

返回失败断言表达式中的比较说明。

返回None表示没有自定义解释,否则返回字符串列表。字符串将由换行符连接,但字符串中的任何换行符都将被转义。请注意,除第一行外的所有行都将略微缩进,目的是使第一行成为摘要

Parameters

config (Config) – The pytest config object.

op (str) – The operator, e.g. "==", "!=", "not in".

left (object) – The left operand.

right (object) – The right operand.

例如,考虑在conftest.py文件中添加以下,该文件为Foo对象提供了另一种解释:

# content of conftest.py 
from test_foocompare import Foodef pytest_assertrepr_compare(op, left, right): if isinstance(left, Foo) and isinstance(right, Foo) and op == "==": return [ "Comparing Foo instances:", f"    vals: {left.val} != {right.val}", ]

现在,给定这个测试模块:

# content of test_foocompare.py 
class Foo: def __init__(self, val): self.val = val def __eq__(self, other): return self.val == other.valdef test_compare(): f1 = Foo(1) f2 = Foo(2) assert f1 == f2

您可以运行测试模块并获得conftest文件中定义的自定义输出:

$ pytest -q test_foocompare.py 
F [100%] 
================================= FAILURES ================================= 
_______________________________ test_compare _______________________________ 
def test_compare(): 
f1 = Foo(1) 
f2 = Foo(2) 
> assert f1 == f2 
E assert Comparing Foo instances: 
E vals: 1 != 2 
test_foocompare.py:12: AssertionError 
========================= short test summary info ========================== 
FAILED test_foocompare.py::test_compare - assert Comparing Foo instances: 
1 failed in 0.12s

2.2.6 断言内省细节

关于失败断言的报告细节是通过在运行断言语句之前重写断言语句来实现的。重写断言语句将自省信息放入断言失败消息中。pytest只重写由其测试收集过程直接发现的测试模块,因此支持模块中的断言(本身不是测试模块)不会被重写

您可以通过在导入模块之前调用register_assert_rewrite来手动启用导入模块的断言重写(在根conftest.py中是一个很好的方法)。

为了获得更多信息,Benjamin Peterson写了《pytest新断言重写的幕后》(Behind the scenes of pytest’s new assertion rewriting)。

断言重写在磁盘上缓存文件

pytest会将重写后的模块写回磁盘进行缓存。您可以通过将其添加到conftest.py文件的顶部来禁用此行为(例如,为了避免在大量移动文件的项目中留下过时的.pyc文件):

import sys 
sys.dont_write_bytecode = True

请注意,您仍然可以获得断言自省的好处,唯一的变化是.pyc文件不会缓存在磁盘上。

此外,如果重写无法写入新的.pyc文件,即在只读文件系统或zipfile中,则重写将自动跳过缓存。

禁用断言重写

pytest在导入时通过使用导入挂钩写入新的pyc文件来重写测试模块。大多数情况下,这是透明的。但是,如果您自己使用导入机器,则导入钩子可能会干扰。

如果是这种情况,您有两种选择:

  • 通过将字符串PYTEST_DONT_REWRITE添加到其文档字符串中,禁用对特定模块的重写。
  • 使用--assert=plain禁用所有模块的重写。

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

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

相关文章

6、架构-服务端缓存

为系统引入缓存之前,第一件事情是确认系统是否真的需要缓 存。从开发角度来说,引入缓存会提 高系统复杂度,因为你要考虑缓存的失效、更新、一致性等问题;从运维角度来说,缓存会掩盖一些缺 陷,让问题在更久的…

npm彻底清理缓存

在使用npm过程中,肯定会遇到清缓存的情况,网上的命令一般为 npm cache clear --force有时笔者在清理缓存之后npm install依然失败,仔细发现,执行该命令之后npm报了一个警告 npm WARN using --force Recommended protections dis…

代码随想录算法训练营第27天|● 39. 组合总和● 40.组合总和II● 131.分割回文串

组合总和 题目链接 39. 组合总和 - 力扣&#xff08;LeetCode&#xff09; 代码&#xff1a; class Solution {public List<List<Integer>> res new ArrayList<>();public List<Integer> list new ArrayList<>();public int sum 0;/**…

在nginx中配置反向代理

在nginx中配置反向代理&#xff0c;需要使用proxy_pass指令。以下是一个简单的nginx反向代理配置示例&#xff1a; server {listen 80;server_name example.com;location / {proxy_pass http://backend_server;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote…

LoadRunner 录制脚本时提示无Internet访问/加载慢,如何解决?

LoadRunner 录制脚本时提示无Internet访问/加载慢&#xff0c;如何解决&#xff1f; 在使用LoadRunner 12.02 进行录制脚本时提示无Internet访问&#xff0c;这是如下图&#xff1a; 翻译中文如下&#xff1a; 这里&#xff0c;我认为大家应该都已经点过yes了&#xff0c;但是…

python结构化模式匹配switch-case,Python 3.10中引入,Python的模式匹配(pattern matching)语法

增加了采用模式加上相应动作的 match 语句 和 case 语句 的形式的结构化模式匹配。 模式由序列、映射、基本数据类型以及类实例构成。 模式匹配使得程序能够从复杂的数据类型中提取信息、根据数据结构实现分支&#xff0c;并基于不同的数据形式应用特定的动作。 语法与操作 模…

Linux下配置Pytorch

1.Anaconda 1.1虚拟环境创建 2.Nvidia驱动 3.CUDA驱动安装 4.Pytorch安装 具体的步骤如上&#xff1a;可参考另一位博主的博客非常详细&#xff1a; Linux服务器配置PythonPyTorchCUDA深度学习环境_linux cuda环境配置-CSDN博客https://blog.csdn.net/NSJim/article/detai…

极海APM32F072用Keil5烧录失败Error: Flash Download failed -“Cortex-MO+“

在用Keil5烧录时&#xff0c;出现错误弹窗&#xff0c;大概长这样&#xff1a; 检查了一圈设置&#xff0c;都搞不好。 先用J-Flash&#xff0c;显示读写保护&#xff08;未截图&#xff09;&#xff0c;会跳出界面让选择是否解除读写保护&#xff1a; 1.点击允许读操作YES&am…

DNF手游攻略:0氪攻略,转职技巧与避坑指南!

在DNF手游的冒险旅程中&#xff0c;角色的转职是一次重要的成长经历。通过转职&#xff0c;玩家可以获得全新的技能和属性&#xff0c;提升自己在地下城中的战斗力。本文将为您介绍转职后的关键技巧和日常任务&#xff0c;帮助您更好地适应新的职业身份&#xff0c;成为地下城中…

Python从0到100(二十九):requests模块处理cookie

1 爬虫中使用cookie 为了能够通过爬虫获取到登录后的页面&#xff0c;或者是解决通过cookie的反扒&#xff0c;需要使用request来处理cookie相关的请求 1.1 爬虫中使用cookie的利弊 带上cookie的好处 能够访问登录后的页面能够实现部分反反爬 带上cookie的坏处 一套cookie往往…

数据库与低代码开发:技术革新与应用实践

在数字化时代&#xff0c;企业对软件开发的需求日益增长&#xff0c;同时对开发效率和成本控制的要求也越来越高。在这样的背景下&#xff0c;低代码开发平台应运而生&#xff0c;它允许开发者通过图形界面和配置化操作&#xff0c;快速构建应用程序&#xff0c;而无需编写大量…

【设计模式】JAVA Design Patterns——Monitor(监视器模式)

&#x1f50d;目的 主要目的是为多个线程或进程提供一种结构化和受控的方式来安全地访问和操作共享资源&#xff0c;例如变量、数据结构或代码的关键部分&#xff0c;而不会导致冲突或竞争条件。 &#x1f50d;解释 通俗描述 监视器模式用于强制对数据进行单线程访问。 一次只允…

Windows线程同步的四种方式和区别

1. Windows线程同步的四种方式 2. 区别 Critical Section更多强调的是保护&#xff0c;Event对象、Mutex对象与Semaphore对象更多的强调的是同步&#xff1b;Critical Section对象是无法设置等待超时的&#xff0c;而其他三个对象则可以设置等待超时&#xff0c;从这一点来讲…

ROS2在RVIZ2中加载机器人urdf模型

参考ROS2-rviz2显示模型 我这边用的solid works生成的urdf以及meshes&#xff0c;比参考的方法多了meshes 问题一&#xff1a;Error retrieving file [package://rm_dcr_description/meshes/leftarm_link7.STL]: Package [rm_dcr_description] does not exist 这个是urdf模型中…

VisualStudio中:如果某个项目不显示SVN的show log等,而其他项目都正常

VisualStudio中&#xff1a;如果某个项目不显示SVN的show log等&#xff0c;而其他项目都正常。说明大概率是当前项目的问题&#xff0c;而不是VisualStudio的问题&#xff01; 1.这个项目内有一个“隐藏”文件夹.svn 》先删除&#xff01; 2.如果外层文件夹有红色感叹号&…

2024-5-14——完成所有任务需要的最少轮数

2024-5-14 题目来源我的题解方法一 哈希表数学 题目来源 力扣每日一题&#xff1b;题序&#xff1a;2244 我的题解 方法一 哈希表数学 根据数学规律可以发现&#xff0c;除了只有1个任务时不能完成任务&#xff0c;其他的都可以完成。并且需要的轮数为&#xff1a; ⌈x/3⌉ …

16、matlab求导、求偏导、求定积分、不定积分、数值积分和数值二重积分

1、matlab求导,diff()函数 1)一阶导数 语法:diff(f(x)):求一阶导数 //diff(f(x),n):求n阶导数(n为具体正整数) 以函数(cos(x)+sin(x)-x^2)的一阶导数为例 一阶导数代码: yms x;%声明符号变量x f(x)=cos(x)+sin(x)-x^2;%定义原式子 dy=diff(f(x))%求一阶导数dy =cos(…

机器学习-12-开源的机器学习可视化拖拉拽工具orange3的应用

参考orange3,一个无敌的 Python 库! 参考orange3的GitHub地址 参考orange3的官方应用示例 参考下载Orange模块,总是出错? 参考Orange3入门(Orange3Dev) 参考工具|Orange 3:机器学习入门神器 1 orange3 数据科学和机器学习是当今科技领域的重要组成部分,而数据分析和建…

Csv--01--ExportUtil 写文件

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 ExportUtil案例&#xff1a; ExportUtil.writeCsvFile ExportUtil import com.alibaba.fastjson.JSON; import com.google.common.collect.Lists;import org.apache…

记录request中上传图片接口的测试过程

F12抓取的接口地址如下&#xff1a; 入参&#xff1a; 注意圈出来的部分参数 apifox调试接口 python相关代码&#xff1a; 接口调用相关文件&#xff1a; select_photo.py 输出结果&#xff1a; 相关接口的一些封装&#xff1a;