如何让 PyC​​harm 显示来自 pytest 的整个错误差异?

Posted

技术标签:

【中文标题】如何让 PyC​​harm 显示来自 pytest 的整个错误差异?【英文标题】:How do I get PyCharm to show entire error diffs from pytest? 【发布时间】:2018-11-09 12:44:27 【问题描述】:

我正在使用Pycharm 运行我的pytest 单元测试。我正在测试一个 REST API,所以我经常需要验证 JSON 块。当测试失败时,我会看到如下内容:

FAILED
test_document_api.py:0 (test_create_documents)
'items': ['i...ages': 1, ... != 'items': ['...ages': 1, ...

Expected :'items': ['...ages': 1, ...
Actual   :'items': ['i...ages': 1, ...
 <Click to see difference>

当我点击“点击查看差异”链接时,大部分差异都会转换为椭圆的点,就像这样

这是没用的,因为它没有告诉我有什么不同。对于大于单个字符串或数字的任何差异,我都会得到这种行为。

我假设 Pycharm 和/或 pytest 试图省略大输出差异的无信息部分。但是,这里太激进了,什么都忽略了。

如何让 Pycharm 和/或 pytest 向我展示全部差异?

我尝试将-vvv 添加到 pytest 的附加参数中,但没有效果。


自从原始帖子以来,我验证了当我从命令行运行单元测试时,我看到了相同的行为。所以这是 pytest 而不是 Pycharm 的问题。

查看到目前为止我得到的答案后,我想我真正要问的是“在 pytest 中是否可以在不更改测试源代码的情况下设置maxDiff=None?”我从阅读 pytest 获得的印象是 -vv 开关控制此设置,但事实并非如此。

【问题讨论】:

【参考方案1】:

由于 pytest 与 unittest 集成,作为一种解决方法,您可以将其设置为 unittest,然后设置 Test.maxDiff = None 或每个特定测试 self.maxDiff = None

https://docs.pytest.org/en/latest/index.html

可以开箱即用地运行单元测试(包括试用)和鼻子测试套件;

这些可能也有帮助...

https://***.com/a/21615720/9530790

https://***.com/a/23617918/9530790

【讨论】:

【参考方案2】:

If you look closely into PyCharm sources,从整个pytest 输出中,PyCharm 使用单行解析数据以显示在Click to see difference 对话框中。这是AssertionError: &lt;message&gt; 行:

def test_spam():
>       assert v1 == v2
E       AssertionError: assert 'foo': 'bar' == 'foo': 'baz'
E         Differing items:
E         'foo': 'bar' != 'foo': 'baz'
E         Use -v to get the full diff

如果您想查看完整的差异行而不被截断,您需要在输出中自定义此行。对于单个测试,这可以通过在assert 语句中添加自定义消息来完成:

def test_eggs():
    assert a == b, '0 != 1'.format(a, b)

如果您想将此行为应用于所有测试,请定义自定义 pytest_assertrepr_compare 挂钩。在conftest.py 文件中:

# conftest.py
def pytest_assertrepr_compare(config, op, left, right):
    if op in ('==', '!='):
        return ['0 1 2'.format(left, op, right)]

值的相等比较现在仍然会在太长时被剥离;要显示完整的行,您仍然需要使用 -vv 标志增加详细程度。

现在AssertionError 行中的值的相等比较将不会被剥离,完整的差异会显示在Click to see difference 对话框中,突出显示差异部分:

【讨论】:

感谢您的回答,我继续提出拉取请求:github.com/JetBrains/intellij-community/pull/1091 @Ilya 您是否跟进了 jetbrain 的评论并将 PR 转发到 teamcity-messages ? @AdrienH 是的,它被合并了:github.com/JetBrains/teamcity-messages/pull/210 -- 应该在最新的 PyCharm 中修复【参考方案3】:

查看了 pytest 代码库,也许您可​​以尝试其中一些:

1) 在测试执行中设置详细级别:

./app_main --pytest --verbose test-suite/

2) 为“CI”或“BUILD_NUMBER”添加环境变量。在链接中 截断文件,您可以看到这些环境变量用于 判断截断块是否运行。

import os

os.environ["BUILD_NUMBER"] = '1'
os.environ["CI"] = 'CI_BUILD'

3) 尝试在截断模块上设置 DEFAULT_MAX_LINES 和 DEFAULT_MAX_CHARS(不推荐这样做,因为它使用私有模块):

from _pytest.assertion import truncate

truncate.DEFAULT_MAX_CHARS = 1000
truncate.DEFAULT_MAX_LINES = 1000

根据代码,-vv 选项应该可以工作,所以奇怪的是它不适合你:

当前的默认行为是在 ~8 条终端线,除非在“-vv”模式下运行或在 CI 上运行。

我的答案基于 Pytest 截断文件:pytest/truncate.py

希望这里能帮到你!

【讨论】:

【参考方案4】:

我遇到了类似的事情,并创建了一个函数,该函数返回一个字符串,其中两个 dicts 的差异很大。在pytest 样式测试中,这看起来像:

assert expected == actual, build_diff_string(expected, actual)

并且采用unittest 风格

self.assertEqual(expected, actual, build_diff_string(expected, actual)

缺点是你必须修改所有有这个问题的测试,但这是一个保持简单和愚蠢的解决方案。

【讨论】:

【参考方案5】:

在 pycharm 中,您只需将 -vv 放在运行配置的 Additional Arguments 字段中,这应该可以解决问题。

或者至少,它在我的机器上工作......

【讨论】:

【参考方案6】:

我在断言中有一些 getattr,但在 AssertionError 之后它从不显示任何内容。

我在Additional Arguments 字段中添加-lv 以显示局部变量。

【讨论】:

以上是关于如何让 PyC​​harm 显示来自 pytest 的整个错误差异?的主要内容,如果未能解决你的问题,请参考以下文章

如何让 PyC​​harm 从我的本地包存储库更新?

让 PyC​​harm 在 windows linux 子系统上识别 python(windows 上的 bash)

PyCharm - 社区版是不是能够突出显示 css/javascript?

如何强制 PyCharm 警告未声明的类型?

未解决的参考:PyCharm 中的“django”错误

PyCharm:自动对齐内嵌注释