python - 使用 pytest + Pycharm 处理长字符串的烦人差异格式
问题描述
嗨有这个非常基本的测试:
def test_long_diff():
long_str1 = "ABCDEFGHIJ " * 10
long_str2 = "ABCDEFGHIJ " * 5 + "* " + "ABCDEFGHIJ " * 5
assert long_str1 == long_str2
使用:Python 3.8.5、pytest-6.2.1、PyCharm 2020.2、MacOs
从 shell 使用 pytest 运行,输出为“可用”,错误消息将指出长字符串中的错误字符:
(venv) ~/dev/testdiff/> pytest longdiff.py
========== test session starts ===========
platform darwin -- Python 3.8.5, pytest-6.2.1, py-1.10.0, pluggy-0.13.1
[...]
> assert long_str1 == long_str2
E AssertionError: assert 'ABCDEFGHIJ A...J ABCDEFGHIJ ' == 'ABCDEFGHIJ A...J ABCDEFGHIJ '
E Skipping 45 identical leading characters in diff, use -v to show
E - BCDEFGHIJ * ABCDEFGHIJ ABCDEFGHIJ ABCDEFGHIJ ABCDEFGHIJ ABCDEFGHIJ
E ? --
E + BCDEFGHIJ ABCDEFGHIJ ABCDEFGHIJ ABCDEFGHIJ ABCDEFGHIJ ABCDEFGHIJ
使用 pytest-clarity 和-vv
选项,我得到彩色差异(未呈现如下)和不同的细节:
E left: "ABCDEFGHIJ ABCDEFGHIJ ABCDEFGHIJ ABCDEFGHIJ ABCDEFGHIJ ABCDEFGHIJ ABCDEFGHIJ ABCDEFGHIJ ABCDEFGHIJ ABCDEFGHIJ "
E right: "ABCDEFGHIJ ABCDEFGHIJ ABCDEFGHIJ ABCDEFGHIJ ABCDEFGHIJ * ABCDEFGHIJ ABCDEFGHIJ ABCDEFGHIJ ABCDEFGHIJ ABCDEFGHIJ "
E
E left and right have different lengths:
E len(left) == 110, len(right) == 112
但是,如果我让 Pycharm 运行测试(相同的 Python 版本,相同的 .venv,我只需右键单击测试并选择“Run 'pytest for ...'”),运行控制台中的输出几乎无法使用,因为“某事一路走来”在应用差异之前将长字符串转换为较短字符串的元组:
FAILED [100%]
longdiff.py:0 (test_long_diff)
('ABCDEFGHIJ ABCDEFGHIJ ABCDEFGHIJ ABCDEFGHIJ ABCDEFGHIJ ABCDEFGHIJ ABCDEFGHIJ '
'ABCDEFGHIJ ABCDEFGHIJ ABCDEFGHIJ ') != ('ABCDEFGHIJ ABCDEFGHIJ ABCDEFGHIJ ABCDEFGHIJ ABCDEFGHIJ * ABCDEFGHIJ '
'ABCDEFGHIJ ABCDEFGHIJ ABCDEFGHIJ ABCDEFGHIJ ')
<Click to see difference>
单击<Click to see difference>
基本上在更大的窗口中显示相同的乱码输出
是什么导致了这个 Pycharm 输出?有没有办法防止这种行为?理想情况下,我希望在运行控制台中查看 pytest-clarity 的输出。
解决方案
所以事实证明这是 PyCharm 使用的 pytest 插件的硬编码行为。该插件始终适用 pprint.pformat()
于左右值。
当字符串长度超过 80 个字符并包含空格时,就会出现问题中描述的行为。
一种可能的解决方法是覆盖插件的pytest_assertrepr_compare
钩子。这是一个对我有用的版本。只需将其粘贴到您的conftest.py
.
import pprint
import pytest
@pytest.hookimpl(tryfirst=True)
def pytest_assertrepr_compare(config, op, left, right):
if op in ('==', '!='):
return ['{0} {1} {2}'.format(pprint.pformat(left, width=999), op, pprint.pformat(right, width=999))]
另一种可能的破解它到 monkeypatch pprint.pformat
:
import pytest
import pprint
from functools import partial
@pytest.fixture(scope='function', autouse=True)
def fix_long_string_diffs(monkeypatch):
monkeypatch.setattr(pprint, 'pformat', partial(pprint.pformat, width=999))
推荐阅读
- java - 如何解决snakeyaml NoSuchMethodError:getStyle()
- entity-framework - 实体框架在 SaveChanges 之前检查 DbUpdateException
- javascript - Recharts - 在左侧对齐轴标签
- maven - 谷歌 BigTable 访问错误
- java - 使用 RxJava 进行意外的类型推断
- javascript - 如何将一个对象数组插入另一个数组?
- python - requests.exceptions.ReadTImeout 未捕获
- javascript - Sails.js - 带有正则表达式的航行路线
- mysql - MariaDb timediff 函数正在计算错误的小时数
- angular - Angular 自定义表单组件和 clearValidators