我正在尝试编写一个pytest插件来自定义特定异常的外观 - 更具体地说,模拟异常(预期被调用的方法没有被调用等),因为在这些异常的追溯中存在大量无用的噪声.
这是我到目前为止所做的,它有效,但非常黑客:
import pytest
import flexmock
@pytest.hookimpl()
def pytest_exception_interact(node, call, report):
exc_type = call.excinfo.type
if exc_type == flexmock.MethodCallError:
entry = report.longrepr.reprtraceback.reprentries[-1]
entry.style = 'short'
entry.lines = [entry.lines[-1]]
report.longrepr.reprtraceback.reprentries = [entry]
Run Code Online (Sandbox Code Playgroud)
我认为我正在hookimpl
使用简单的if语句检查异常类型.
我尝试report.longrepr
用一个简单的字符串替换,这也有效,但后来我失去了格式化(终端中的颜色).
作为我想缩短的输出类型的一个例子,这是一个模拟断言失败:
=================================== FAILURES ====================================
_______________________ test_session_calls_remote_client ________________________
def test_session_calls_remote_client():
remote_client = mock.Mock()
session = _make_session(remote_client)
session.connect()
remote_client.connect.assert_called_once_with()
session.run_action('asdf')
> remote_client.run_action.assert_called_once_with('asdff')
tests/unit/executor/remote_test.py:22:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/opt/python-3.6.3/lib/python3.6/unittest/mock.py:825: in assert_called_once_with
return self.assert_called_with(*args, **kwargs)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
_mock_self = <Mock name='mock.run_action' id='139987553103944'>
args = ('asdff',), kwargs = {}, expected = (('asdff',), {})
_error_message = <function NonCallableMock.assert_called_with.<locals>._error_message at 0x7f51646269d8>
actual = call('asdf'), cause = None
def assert_called_with(_mock_self, *args, **kwargs):
"""assert that the mock was called with the specified arguments.
Raises an AssertionError if the args and keyword args passed in are
different to the last call to the mock."""
self = _mock_self
if self.call_args is None:
expected = self._format_mock_call_signature(args, kwargs)
raise AssertionError('Expected call: %s\nNot called' % (expected,))
def _error_message():
msg = self._format_mock_failure_message(args, kwargs)
return msg
expected = self._call_matcher((args, kwargs))
actual = self._call_matcher(self.call_args)
if expected != actual:
cause = expected if isinstance(expected, Exception) else None
> raise AssertionError(_error_message()) from cause
E AssertionError: Expected call: run_action('asdff')
E Actual call: run_action('asdf')
/opt/python-3.6.3/lib/python3.6/unittest/mock.py:814: AssertionError
====================== 1 failed, 30 passed in 0.28 seconds ======================
Run Code Online (Sandbox Code Playgroud)
小智 1
如果您的目标是使堆栈跟踪更易于阅读,那么您可以使用以下代码块输出自定义错误消息。此自定义错误消息出现在堆栈跟踪的末尾,因此您无需向上滚动:
with raises(ZeroDivisionError, message="Expecting ZeroDivisionError"):
pass
--> Failed: Expecting ZeroDivisionError
Run Code Online (Sandbox Code Playgroud)
来源:pytest 的文档。因此,您可以通过 grep 等管道输出 pytest 的输出,并过滤掉堆栈跟踪中无用的部分,而不是制作插件。
根据我在文档中读到的内容,您正在使用正确的 pytest 装饰器和钩子函数(pytest_exception_interact
)。但是,可能不需要对错误进行类型检查。文档的这一部分说“仅当引发的异常不是像skip.Exception这样的内部异常时才会调用此钩子。”
归档时间: |
|
查看次数: |
984 次 |
最近记录: |