assert用法总结

 

assert宏的原型定义在<assert.h>中,其作用是如果它的条件返回错误,则终止程序执行,原型定义:
#include <assert.h>
void assert( int expression );

assert的作用是现计算表达式 expression ,如果其值为假(即为0),那么它先向stderr打印一条出错信息,
然后通过调用 abort 来终止程序运行。

请看下面的程序清单badptr.c:
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>

int main( void )
{
       FILE *fp;
    
       fp = fopen( "test.txt", "w" );//以可写的方式打开一个文件,如果不存在就创建一个同名文件
       assert( fp );                           //所以这里不会出错
       fclose( fp );
    
       fp = fopen( "noexitfile.txt", "r" );//以只读的方式打开一个文件,如果不存在就打开文件失败
       assert( fp );                           //所以这里出错
       fclose( fp );                           //程序永远都执行不到这里来

       return 0;
}

[root@localhost error_process]# gcc badptr.c 
[root@localhost error_process]# ./a.out 
a.out: badptr.c:14: main: Assertion `fp' failed.
已放弃

使用assert的缺点是,频繁的调用会极大的影响程序的性能,增加额外的开销。
在调试结束后,可以通过在包含#include <assert.h>的语句之前插入 #define NDEBUG 来禁用assert调用,示例代码如下:
#include <stdio.h>
#define NDEBUG
#include <assert.h>

用法总结与注意事项:
1)在函数开始处检验传入参数的合法性
如:

int resetBufferSize(int nNewSize)
{
//功能:改变缓冲区大小,
//参数:nNewSize 缓冲区新长度
//返回值:缓冲区当前长度 
//说明:保持原信息内容不变     nNewSize<=0表示清除缓冲区
assert(nNewSize >= 0);
assert(nNewSize <= MAX_BUFFER_SIZE);

...
}

2)每个assert只检验一个条件,因为同时检验多个条件时,如果断言失败,无法直观的判断是哪个条件失败

不好: assert(nOffset>=0 && nOffset+nSize<=m_nInfomationSize);

好: assert(nOffset >= 0);
assert(nOffset+nSize <= m_nInfomationSize);


3)不能使用改变环境的语句,因为assert只在DEBUG个生效,如果这么做,会使用程序在真正运行时遇到问题
错误: assert(i++ < 100)
这是因为如果出错,比如在执行之前i=100,那么这条语句就不会执行,那么i++这条命令就没有执行。
正确: assert(i < 100)
         i++;
            
      
4)assert和后面的语句应空一行,以形成逻辑和视觉上的一致感

5)有的地方,assert不能代替条件过滤

 

<think>嗯,用户问的是pytest中assert用法,我需要详细说明一下。首先,pytest是基于Python的测试框架,它的断言机制和普通的assert有什么区别呢?对了,pytest会重写assert语句,使其在测试失败时能提供更详细的错误信息。 接下来,得介绍基本用法,比如直接使用assert后面跟表达式,比如assert 1 + 1 == 2。如果失败的话,pytest会显示具体的值,这样用户就知道哪里出错了。然后可能需要举几个例子,比如比较变量、字符串、列表等。 然后是高级用法,比如异常断言,用pytest.raises来捕获预期的异常。比如with pytest.raises(ValueError):然后触发ValueError的操作。这部分要说明如何验证异常类型和消息。 还有,集合或字典的断言,比如检查元素是否存在,可以用assert elem in collection,或者用all()函数判断所有元素满足条件。比如assert all(x > 0 for x in list)。可能需要提醒用户注意这些方法的使用场景。 浮点数的近似比较也是一个点,比如用pytest.approx来避免精度问题,比如assert 0.1 + 0.2 == approx(0.3)。这个要强调浮点数运算的精度问题,以及approx的使用方法。 另外,自定义失败信息,用户可能想在断言失败时添加说明,比如assert a == b, "a和b不相等"。这样测试失败时会显示自定义的信息,帮助调试。 还有,可能需要提到pytest是如何优化断言信息的,比如当比较两个复杂对象时,pytest会显示出差异的部分,而不仅仅是抛出AssertionError。这点对调试很有帮助。 最后,总结一下assert在pytest中的优势,比如简洁、灵活的错误报告,以及结合各种断言方法提高测试可读性。可能还要提醒用户注意常见的错误,比如忘记使用approx导致浮点数比较失败,或者异常断言中没有正确匹配类型或消息。 需要检查是否有遗漏的部分,比如是否覆盖了所有常见的断言场景,或者是否需要给出更多的示例代码。确保语言简洁明了,结构清晰,用户能一步步理解不同情况下的使用方法。</think>在 `pytest` 中,`assert` 是编写测试用例的核心工具,它通过重写 Python 原生的 `assert` 语句,提供更详细的错误信息。以下是具体用法和常见场景: --- ### **1. 基本断言** 直接使用 `assert` 后跟布尔表达式: ```python def test_addition(): result = 1 + 1 assert result == 2 # 断言成功 assert result != 3 # 断言成功 assert result > 1 # 断言成功 ``` 若断言失败,`pytest` 会自动输出详细的错误信息。例如: ```python def test_failure(): a, b = 5, 3 assert a * b == 20 # 失败时会显示 5*3=15 ≠ 20 ``` --- ### **2. 断言异常** 使用 `pytest.raises` 捕获预期异常: ```python import pytest def test_divide_by_zero(): with pytest.raises(ZeroDivisionError): # 断言会抛出指定异常 1 / 0 def test_exception_message(): with pytest.raises(ValueError) as exc_info: int("invalid") # 触发 ValueError assert "invalid literal" in str(exc_info.value) # 验证异常消息 ``` --- ### **3. 集合/字典断言** 检查集合内容: ```python def test_list_contents(): my_list = [1, 2, 3] assert 2 in my_list # 元素存在 assert 0 not in my_list # 元素不存在 assert my_list == [1, 2, 3] # 完整匹配 def test_dict(): d = {"a": 1, "b": 2} assert d["a"] == 1 # 键值匹配 assert "c" not in d # 键不存在 ``` --- ### **4. 近似值断言** 处理浮点数精度问题: ```python from pytest import approx def test_float_equality(): assert 0.1 + 0.2 == approx(0.3) # 默认容差为 1e-6 assert 1.000001 == approx(1, abs=1e-3) # 绝对容差 assert 99 == approx(100, rel=0.02) # 相对容差 2% ``` --- ### **5. 复杂条件断言** 使用逻辑表达式或辅助函数: ```python def test_all_elements_positive(): numbers = [1, 2, 3] assert all(x > 0 for x in numbers) # 所有元素满足条件 def test_any_negative(): numbers = [1, -2, 3] assert any(x < 0 for x in numbers) # 至少一个元素满足条件 ``` --- ### **6. 自定义失败信息** 添加断言失败的说明: ```python def test_custom_message(): a, b = 5, 3 assert a * b == 20, f"实际结果为 {a*b},预期为 20" ``` --- ### **断言优化特性** `pytest` 会自动解析断言表达式,展示更清晰的错误细节。例如: ```python def test_complex_objects(): expected = {"name": "Alice", "age": 30} actual = {"name": "Bob", "age": 25} assert actual == expected ``` 失败时会高亮差异: ``` E AssertionError: assert {'name': 'Bob', 'age': 25} == {'name': 'Alice', 'age': 30} E Differing items: E {'name': 'Bob'} != {'name': 'Alice'} E {'age': 25} != {'age': 30} ``` --- ### **总结** `pytest` 的 `assert` 优势: - **简洁性**:无需学习特定断言方法(如 `unittest` 的 `assertEqual`)。 - **灵活性**:支持任意布尔表达式。 - **详细错误信息**:自动展示变量值、集合差异、浮点误差等。 - **扩展性**:结合 `pytest.raises`、`approx` 等工具处理复杂场景。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值