python - 如何模拟/测试报告异常的记录器?
问题描述
你们中的任何人都可以解释为什么以下assert_called_with
不起作用吗?
根据 pytest 打印的信息“预期调用”等于“实际调用”,所以我假设当 pytest 将其转换为 str 以在终端上打印时丢失了一些信息。
你会推荐什么工具来调试它?
程序:
import logging
from mock import patch
logger = logging.getLogger(__name__)
logger.addHandler(logging.StreamHandler())
def func():
try:
raise ValueError("error XYZ")
except ValueError as err:
logger.error(err)
def test_func():
with patch('logging.Logger.error') as log:
func()
log.assert_called_with(ValueError("error XYZ"))
执行:
$ pytest prog.py
=========================================================================== test session starts ===========================================================================
platform linux2 -- Python 2.7.15+, pytest-4.2.0, py-1.7.0, pluggy-0.8.1
rootdir: /tmp, inifile:
collected 1 item
prog.py F [100%]
================================================================================ FAILURES =================================================================================
________________________________________________________________________________ test_func ________________________________________________________________________________
def test_func():
with patch('logging.Logger.error') as log:
func()
> log.assert_called_with(ValueError("error XYZ"))
prog.py:16:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/home/ebajgrz/py27/local/lib/python2.7/site-packages/mock/mock.py:937: in assert_called_with
six.raise_from(AssertionError(_error_message(cause)), cause)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
value = AssertionError("Expected call: error(ValueError('error XYZ',))\nActual call: error(ValueError('error XYZ',))",), from_value = None
def raise_from(value, from_value):
> raise value
E AssertionError: Expected call: error(ValueError('error XYZ',))
E Actual call: error(ValueError('error XYZ',))
/home/ebajgrz/py27/local/lib/python2.7/site-packages/six.py:737: AssertionError
======================================================================== deprecated python version ========================================================================
You are using Python 2.7.15, which will no longer be supported in pytest 5.0
For more information, please read:
https://docs.pytest.org/en/latest/py27-py34-deprecation.html
======================================================================== 1 failed in 0.28 seconds ============================
我意识到 pytest 具有 caplog 并且可以按如下方式实现测试,但我想了解为什么第一种方法不起作用。
def test_func2(caplog):
func()
assert 'error XYZ' in caplog.text
解决方案
这是因为mock
正在检查传入的对象与预期的对象。它们是不同的对象,因此断言失败。例如,打开一个 python shell 并试试这个:
>>> ValueError('bees') == ValueError('bees')
False
它们不相等,因为它们是不同的对象。但是试试这个:
>>> str(ValueError('bees')) == str(ValueError('bees'))
True
这是因为字符串是不可变的。现在,如果您将原始日志调用更改为:logger.error(str(err))
并将您的断言更改为:log.assert_called_with(str(ValueError("error XYZ")))
,我认为您将克服第一个错误。
与此无关,还有更多关于记录异常的建议:您可能希望在这样的 except 块中记录更多信息。像这样的东西:
logger.error('Error raised doing something: %s', str(err), exc_info=True)
推荐阅读
- python-3.x - 以人性化的语法将字符串打印到控制台日志
- arrays - 如何以角度将数据更新为嵌套数组?
- python - 曲线拟合将函数的输入解释为数组和标量
- c# - 可以在 c# 中处理文本的 CSS 选择器
- performance - 如何避免重复/重复的测试数据或避免已经执行的数据而不删除 CSV 文件?
- r - 如何在 r 中获得准确度 xgboost
- events - CommandStateChange 事件不会在 HTA iframe 中触发
- java - 在 Spring 中,直接从服务返回 ResponseEntity 是更好的做法,还是应该在控制器中创建它?
- mysql - 找到总分最高的用户
- c# - .NET 依赖注入与依赖于其他通用服务的通用服务