讲师中心 微信公众号

工具推荐

视频效率加速
立刻MV
立刻MV

低成本歌曲 MV、视频生成

剧云
剧云

中文短剧剧本制作平台

Seko
Seko

AI短剧一键生成成片

Laper
Laper

剧本策划到成片协作

Python pytest 框架中的异常断言

千明君_4178

千明君_4178

发布时间:2025-09-19 22:48:01

|

711人浏览过

|

来源于php中文网

原创

使用pytest.raises可精确断言异常类型和错误信息,通过上下文管理器捕获异常,并用match参数验证错误消息是否匹配字符串或正则;结合as excinfo可访问异常实例的属性和类型,确保自定义异常的完整性和上下文正确,从而提升测试的健壮性与代码可靠性。

python pytest 框架中的异常断言

在Python的

pytest
框架中,异常断言是确保代码在特定条件下能正确抛出预期错误的关键机制。它让我们能够验证程序的错误处理逻辑是否健全,而不是仅仅关注正常的执行路径。

当我们需要验证一段代码是否会按预期抛出异常时,

pytest.raises
是一个极其强大且直观的工具。它允许我们捕获并检查异常的类型、消息,甚至是异常对象本身的更多细节。

如何在 pytest 中精确地断言异常类型和错误信息?

在编写测试时,我们往往不只是想知道“有没有抛异常”,更想知道“抛的是不是对的异常,消息对不对”。

pytest.raises
在这方面提供了非常精细的控制。

通常,我们会使用

with pytest.raises(ExpectedExceptionType)
这样的上下文管理器。比如,如果我有一个函数
divide(a, b)
,当
b
为零时它应该抛出
ZeroDivisionError
,我的测试会是这样:

立即学习“Python免费学习笔记(深入)”;

def divide(a, b):
    if b == 0:
        raise ZeroDivisionError("除数不能为零")
    return a / b

def test_divide_by_zero():
    with pytest.raises(ZeroDivisionError):
        divide(1, 0)

这仅仅验证了异常类型。但如果我想更进一步,确认异常消息也符合预期呢?

pytest.raises
的
match
参数就派上用场了。它可以接受一个正则表达式或一个字符串,用于匹配异常的详细信息。

import pytest

def divide(a, b):
    if b == 0:
        raise ZeroDivisionError("除数不能为零,请检查输入")
    return a / b

def test_divide_by_zero_with_message():
    # 使用字符串匹配
    with pytest.raises(ZeroDivisionError, match="除数不能为零"):
        divide(1, 0)

    # 也可以使用正则表达式,更灵活
    with pytest.raises(ZeroDivisionError, match=r"除数不能为零.*检查输入"):
        divide(1, 0)

    # 假设有个自定义异常
    class MyCustomError(ValueError):
        pass

    def do_something_risky(value):
        if value < 0:
            raise MyCustomError("负数是不允许的!")

    with pytest.raises(MyCustomError, match="负数是不允许的!"):
        do_something_risky(-5)

这种精确的匹配,尤其是在处理复杂的业务逻辑或外部API错误时,显得尤为重要。它能确保我们的错误信息不仅存在,而且是用户或开发者能够理解、并据此采取行动的。毕竟,一个含糊不清的错误信息,和没有错误信息也差不了多少。

处理预期之外的异常行为,pytest 有哪些高级用法?

有时,我们不仅要断言异常的抛出,还需要在异常抛出后,对异常对象本身进行更深入的检查。

pytest.raises
上下文管理器返回的
ExceptionInfo
对象就提供了这种能力。通过
as excinfo
语法,我们可以捕获到这个对象。

import pytest

class ConfigurationError(Exception):
    def __init__(self, message, config_key=None):
        super().__init__(message)
        self.config_key = config_key

def load_config(settings):
    if "database_url" not in settings:
        raise ConfigurationError("缺少数据库连接配置", config_key="database_url")
    return True

def test_missing_database_config():
    with pytest.raises(ConfigurationError) as excinfo:
        load_config({})

    # 检查异常类型
    assert excinfo.type is ConfigurationError
    # 检查异常消息
    assert "缺少数据库连接配置" in str(excinfo.value)
    # 检查自定义属性
    assert excinfo.value.config_key == "database_url"

    # 甚至可以检查异常的traceback
    # assert "load_config" in str(excinfo.traceback) # 通常不推荐直接断言traceback字符串,但知道有这个能力

这里

excinfo.value
就是实际抛出的异常实例。我们可以访问它的任何属性,包括自定义的属性。这对于那些携带额外上下文信息的异常(比如我们自定义的
ConfigurationError
,它有一个
config_key
属性)来说,是极其有用的。它让我们能验证异常不仅仅是类型正确,其内部状态也符合预期。

Python Hardener
Python Hardener

通过完整的安全审查、代码整洁重构、健壮的错误处理、正确的日志记录以及完整的文档字符串覆盖,强化 Python 脚本。

下载

再比如,我们可能需要测试一个函数,它可能会因为多种原因抛出异常,但我们只关心其中一种。或者,我们想确保某个函数在特定条件下绝不抛出异常。虽然

pytest.raises
主要是为了断言异常的抛出,但如果一个函数在不应该抛出异常时抛出了,测试自然会失败。

对于那些可能抛出多种异常的场景,我们可以在

pytest.raises
中传入一个元组,来断言多种可能的异常类型:

import pytest

def risky_operation(value):
    if value == 0:
        raise ValueError("零值无效")
    if value < 0:
        raise TypeError("负数类型不符")
    return 1 / value

def test_risky_operation_exceptions():
    # 期望抛出ValueError或TypeError
    with pytest.raises((ValueError, TypeError)):
        risky_operation(0)
    with pytest.raises((ValueError, TypeError)):
        risky_operation(-1)

    # 仍然可以检查具体消息
    with pytest.raises(ValueError, match="零值无效"):
        risky_operation(0)

这种处理方式让我们的测试更加健壮,能够覆盖到更多潜在的错误路径。

为什么在测试中异常断言如此重要,它能避免哪些潜在问题?

异常断言在测试策略中扮演着一个不可或缺的角色。它不仅仅是代码覆盖率的一个数字,更是我们对程序健壮性和可靠性承诺的体现。

首先,它确保了错误处理逻辑的正确性。很多时候,我们写下

try...except
块,但很少真正去验证当异常发生时,我们的
except
块是否真的被执行了,或者它是否处理了正确的异常类型。异常断言就是这块缺失的拼图。它强制我们思考:在什么情况下,我的代码会失败?失败时,它应该如何表现?

其次,异常断言是API契约的有效保障。当你开发一个库或模块时,你可能会约定在输入不合法时抛出特定的异常。例如,一个接受文件路径的函数,如果路径不存在,就应该抛出

FileNotFoundError
。通过测试这些异常,我们实际上是在验证我们的API行为符合预期,为使用者提供清晰、可预测的错误反馈。如果后续有人修改了代码,不小心改变了异常行为,测试会立即发现。

再者,它有助于避免“静默失败”。最糟糕的错误往往是那些不声不响就发生了的。如果一个函数在遇到问题时,不是抛出异常,而是返回一个

None
或者一个空列表,那么调用者可能不会立即意识到问题,导致错误在系统深处才被发现,排查起来异常困难。异常断言迫使我们明确地定义和测试这些失败点,确保问题能够及时、明确地暴露出来。

从个人经验来看,我曾遇到过这样的情况:一个关键的配置加载函数,在配置项缺失时,本应抛出

ConfigurationError
,但由于开发人员的疏忽,它只是默默地返回了一个默认值,导致下游组件在运行时行为异常,且难以追踪源头。如果当时有针对性的异常断言,这个问题会在第一时间被发现,并修复。

所以,异常断言不仅仅是测试的一种手段,它更是防御性编程思想在测试层面的体现。它帮助我们构建更稳定、更可靠、更易于维护的软件系统。它让我们在面对各种不可预见的情况时,能够更加自信地说:“我的代码知道如何应对。”

热门AI工具

更多
火山引擎

火山引擎是一款面向企业的云计算与AI服务平台。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

SkildArt
SkildArt Hot

SkildArt是一款AI文本写作工具,一站式 AI 视觉创作平台。

Flowith
Flowith Hot

Flowith是一款基于画布和智能体工作流的 AI 协作工作空间。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

PixPix
PixPix Hot

PixPix是一款面向电商视觉生产的AI商品图生成工具。

蛙蛙写作

一款AI论文写作工具,主要用于超级AI智能写作助手,适合需要提升相关任务效率的用户。

Laper
Laper Hot

Laper是专为编剧、导演和制片人推出的 AI 原生剧本创作工具。

相关专题

更多
js正则表达式
js正则表达式

php中文网为大家提供各种js正则表达式语法大全以及各种js正则表达式使用的方法,还有更多js正则表达式的相关文章、相关下载、相关课程,供大家免费下载体验。

4976

2023.06.20

正则表达式不包含
正则表达式不包含

正则表达式,又称规则表达式,,是一种文本模式,包括普通字符和特殊字符,是计算机科学的一个概念。正则表达式使用单个字符串来描述、匹配一系列匹配某个句法规则的字符串,通常被用来检索、替换那些符合某个模式的文本。php中文网给大家带来了有关正则表达式的相关教程以及文章,希望对大家能有所帮助。

3421

2023.07.05

java正则表达式语法
java正则表达式语法

java正则表达式语法是一种模式匹配工具,它非常有用,可以在处理文本和字符串时快速地查找、替换、验证和提取特定的模式和数据。本专题提供java正则表达式语法的相关文章、下载和专题,供大家免费下载体验。

9562

2023.07.05

java正则表达式匹配字符串
java正则表达式匹配字符串

在Java中,我们可以使用正则表达式来匹配字符串。本专题为大家带来java正则表达式匹配字符串的相关内容,帮助大家解决问题。

832

2023.08.11

正则表达式空格
正则表达式空格

正则表达式空格可以用“s”来表示,它是一个特殊的元字符,用于匹配任意空白字符,包括空格、制表符、换行符等。本专题为大家提供正则表达式相关的文章、下载、课程内容,供大家免费下载体验。

540

2023.08.31

Python爬虫获取数据的方法
Python爬虫获取数据的方法

Python爬虫可以通过请求库发送HTTP请求、解析库解析HTML、正则表达式提取数据,或使用数据抓取框架来获取数据。更多关于Python爬虫相关知识。详情阅读本专题下面的文章。php中文网欢迎大家前来学习。

693

2023.11.13

正则表达式空格如何表示
正则表达式空格如何表示

正则表达式空格可以用“s”来表示,它是一个特殊的元字符,用于匹配任意空白字符,包括空格、制表符、换行符等。想了解更多正则表达式空格怎么表示的内容,可以访问下面的文章。

406

2023.11.17

正则表达式中如何匹配数字
正则表达式中如何匹配数字

正则表达式中可以通过匹配单个数字、匹配多个数字、匹配固定长度的数字、匹配整数和小数、匹配负数和匹配科学计数法表示的数字的方法匹配数字。更多关于正则表达式的相关知识详情请看本专题下面的文章。php中文网欢迎大家前来学习。

739

2023.12.06

Go-Zero API开发使用教程
Go-Zero API开发使用教程

本专题聚焦Go-Zero的API开发,拆解.api描述文件的语法结构、路由与分组定义、参数绑定与校验规则,说明统一响应体、JWT鉴权、跨域与接口文档生成的落地方式,并给出网关聚合与接口测试的实践建议。

0

2026.11.12

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn