py.test:从 unittest 模块隐藏堆栈跟踪行 [英] py.test: hide stacktrace lines from unittest module
问题描述
py.test 堆栈跟踪目前看起来像这样:
py.test stacktraces look like this at the moment:
Traceback (most recent call last):
File "/home/foo_tbz_di476/src/djangotools/djangotools/tests/ReadonlyModelTestCommon.py", line 788, in test_stale_or_missing_content_types
self.assertEqual([], errors, 'Stale/Missing ContentTypes: %s' % '\n'.join(errors))
File "/usr/lib64/python2.7/unittest/case.py", line 511, in assertEqual
assertion_func(first, second, msg=msg)
File "/usr/lib64/python2.7/unittest/case.py", line 740, in assertListEqual
self.assertSequenceEqual(list1, list2, msg, seq_type=list)
File "/usr/lib64/python2.7/unittest/case.py", line 722, in assertSequenceEqual
self.fail(msg)
File "/usr/lib64/python2.7/unittest/case.py", line 408, in fail
raise self.failureException(msg)
如果输出跳过 unittest
模块中的行,对我的人眼来说会容易得多.
It would be much easier for my human eyes if the output would skip the lines from the unittest
module.
示例:
Traceback (most recent call last):
File "/home/foo_tbz_di476/src/djangotools/djangotools/tests/ReadonlyModelTestCommon.py", line 788, in test_stale_or_missing_content_types
self.assertEqual([], errors, 'Stale/Missing ContentTypes: %s' % '\n'.join(errors))
我尝试了选项 --tb=short
但这并没有做到这一点.
I tried option --tb=short
but this does not do this.
更新
首选没有 unix 管道的解决方案(如 py.test ...| grep
).
A solution without a unix pipe (like py.test ...| grep
) is preferred.
推荐答案
看起来你正在调用 pytest 像:
It looks like you are invoking pytest like:
py.test --tb=native
此表单将输出一个派生自 traceback.format_exception 的 python stdlib stacktrace
This form will output a python stdlib stacktrace derived from traceback.format_exception
使用 pytest,您可以添加 conftest.py 文件到您的项目.您可以在此处添加任何代码来修改 pytest 行为.
With pytest you can add a conftest.py file(s) to your project. Here you can add any bits of code to modify pytest behaviour.
当心!在以下两种方法中都使用 monkey patching ,人们可能认为是邪恶的.
Beware! In both the following approaches use monkey patching which people may consider evil.
这是最简单的方法,但如果您要搜索的字符串出现在您不想隐藏的行中,则可能会出现问题.
This is the simplest approach but could be a problem if the string you are searching for appears in a line that you don't want to hide.
此方法修补了 py 包中的 ReprEntryNative 类,该类是 pytest 的依赖项.
This approach patches the ReprEntryNative class in the py package which is a dependancy of pytest.
将以下代码放入你的conftest.py
Put the following code in you conftest.py
import py
def test_skip_line(line):
"""decide which lines to skip, the code below will also skip the next line if this returns true"""
return 'unittest' in line
class PatchedReprEntryNative(py._code.code.ReprEntryNative):
def __init__(self, tblines):
self.lines = []
while len(tblines) > 0:
line = tblines.pop(0)
if test_skip_line(line):
# skip this line and the next
tblines.pop(0)
else:
self.lines.append(line)
py._code.code.ReprEntryNative = PatchedReprEntryNative
选项 2:回溯帧检查
如果字符串匹配对您来说不够真实,我们可以在它转储到字符串之前检查回溯,并且只输出不是来自一组模块的帧.
Option 2: traceback frame inspection
If string matching isnt true enough for you, we can inspect the traceback before it gets dumped to strings and only output frames that aren't from a set of modules.
这种方法修补了可能会杀死小狗的 traceback.extract_tb 函数.
This approach patches the traceback.extract_tb function which probably kills puppies.
将以下代码放入你的conftest.py
Put the following code in you conftest.py
import inspect
import linecache
import traceback
import unittest.case
import sys
SKIPPED_MODULES = [
unittest.case
]
def test_skip_frame(frame):
module = inspect.getmodule(frame)
return module in SKIPPED_MODULES
def tb_skipper(tb):
tbnext = tb.tb_next
while tbnext is not None:
if test_skip_frame(tbnext.tb_frame):
tbnext = tbnext.tb_next
else:
yield tbnext
yield None
def new_extract_tb(tb, limit = None):
if limit is None:
if hasattr(sys, 'tracebacklimit'):
limit = sys.tracebacklimit
list = []
n = 0
new_tb_order = tb_skipper(tb) # <-- this line added
while tb is not None and (limit is None or n < limit):
f = tb.tb_frame
lineno = tb.tb_lineno
co = f.f_code
filename = co.co_filename
name = co.co_name
linecache.checkcache(filename)
line = linecache.getline(filename, lineno, f.f_globals)
if line: line = line.strip()
else: line = None
list.append((filename, lineno, name, line))
tb = next(new_tb_order) # <-- this line modified, was tb = tb.tb_next
n = n+1
return list
traceback.extract_tb = new_extract_tb
这篇关于py.test:从 unittest 模块隐藏堆栈跟踪行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!