Python Pytest:自定义简短测试摘要信息,删除文件路径

Python Pytest:自定义简短测试摘要信息,删除文件路径,python,pytest,Python,Pytest,我试图从pytest-tb=noshort输出中获得更有用的输出。我将集成测试存储在JSON文件中,因此输出看起来非常相似 tests/test_dit_cli.py .......F............................. [ 29%] ...F...F.FF........F............................F...FFFFFFF [ 75%] FFF.F..................F.....FF

我试图从
pytest-tb=no
short输出中获得更有用的输出。我将集成测试存储在JSON文件中,因此输出看起来非常相似

tests/test_dit_cli.py .......F............................. [ 29%]
...F...F.FF........F............................F...FFFFFFF [ 75%]
FFF.F..................F.....FF                             [100%]

===================== short test summary info =====================
FAILED tests/test_dit_cli.py::test_dits[dit_json7] - assert "Lin...
FAILED tests/test_dit_cli.py::test_dits[dit_json40] - assert "Li...
FAILED tests/test_dit_cli.py::test_dits[dit_json44] - assert "Li...
FAILED tests/test_dit_cli.py::test_dits[dit_json46] - assert "Li...
FAILED tests/test_dit_cli.py::test_dits[dit_json47] - assert "Li...
FAILED tests/test_dit_cli.py::test_dits[dit_json56] - assert "Li...
FAILED tests/test_dit_cli.py::test_dits[dit_json85] - assert "Li...
FAILED tests/test_dit_cli.py::test_dits[dit_json89] - AssertionE...
FAILED tests/test_dit_cli.py::test_dits[dit_json90] - AssertionE...
FAILED tests/test_dit_cli.py::test_dits[dit_json91] - AssertionE...
FAILED tests/test_dit_cli.py::test_dits[dit_json92] - AssertionE...
FAILED tests/test_dit_cli.py::test_dits[dit_json93] - AssertionE...
FAILED tests/test_dit_cli.py::test_dits[dit_json94] - AssertionE...
FAILED tests/test_dit_cli.py::test_dits[dit_json95] - AssertionE...
FAILED tests/test_dit_cli.py::test_dits[dit_json96] - assert 'Li...
FAILED tests/test_dit_cli.py::test_dits[dit_json97] - assert 'Li...
FAILED tests/test_dit_cli.py::test_dits[dit_json98] - assert "Li...
FAILED tests/test_dit_cli.py::test_dits[dit_json100] - Assertion...
FAILED tests/test_dit_cli.py::test_dits[dit_json119] - assert "L...
FAILED tests/test_dit_cli.py::test_dits[dit_json125] - Assertion...
FAILED tests/test_dit_cli.py::test_dits[dit_json126] - Assertion...
================= 21 failed, 106 passed in 2.94s ==================
看到同样的
tests/test\u dit\u cli.py::test\u dits[dit\u json126]
20次并不能帮助我了解项目中的错误,所以我通常只需一次通过一个测试来修复错误。每个测试条目都有关于正在运行的测试类型和预期结果的额外信息,但我不知道如何将这些信息输入到pytest中。我希望这样:

===================== short test summary info =====================
FAILED [func, vanilla Python] - assert "Li...
FAILED [Thing, value assignment] - assert "Li...
FAILED [TypeMismatch, String var assigned to List] - assert "Lin...
通过在
参数化
调用中为
ids
提供一个值,我实际上接近了这一点

def pytest_generate_tests(metafunc: Metafunc):
    for fixture in metafunc.fixturenames:
        if fixture == "dit_json":
            test_dicts = list(load_from_json())
            titles = [test_dict["title"] for test_dict in test_dicts]
            metafunc.parametrize(argnames=fixture, argvalues=test_dicts, ids=titles)

所以,我非常接近,我只想删除文件路径,这样行就更短了。有没有办法更改它认为测试所在位置的文件路径?还是一个可以让我任意修改摘要输出的钩子?我试图修改
pytest\u collection\u modifyitems
并更改
item.fspath
,但没有改变输出中的任何内容。我已经看到了修改许多关于输出的其他内容的方法,但没有具体涉及到该文件路径。

如果您只想缩短简短摘要信息中的节点ID,您可以覆盖
报告
对象的
节点ID
属性。一个简单的例子:

def pytest_runtest_logreport(report):
    report.nodeid = "..." + report.nodeid[-10:]
放置在
conftest.py
中,将把每个节点ID截断为其最后十个字符:

=========================== short test summary info ===========================
FAILED ...st_spam[0] - assert False
FAILED ...st_spam[1] - assert False
FAILED ...st_spam[2] - assert False
FAILED ...st_spam[3] - assert False
FAILED ...st_spam[4] - assert False
FAILED ...:test_eggs - assert False
如果您想要一个完全定制的短测试摘要行,您需要实现一个定制的
TerminalReporter
,并在测试运行中尽早替换普通的。示例存根:

import pytest
from _pytest.terminal import TerminalReporter


class MyReporter(TerminalReporter):
    def short_test_summary(self):
        # your own impl goes here, for example:
        self.write_sep("=", "my own short summary info")
        failed = self.stats.get("failed", [])
        for rep in failed:
            self.write_line(f"failed test {rep.nodeid}")


@pytest.mark.trylast
def pytest_configure(config):
    vanilla_reporter = config.pluginmanager.getplugin("terminalreporter")
    my_reporter = MyReporter(config)
    config.pluginmanager.unregister(vanilla_reporter)
    config.pluginmanager.register(my_reporter, "terminalreporter")
这将生成一个摘要部分,如

========================== short test summary info ===========================
failed test tests/test_spam.py::test_spam[0]
failed test tests/test_spam.py::test_spam[1]
failed test tests/test_spam.py::test_spam[2]
failed test tests/test_spam.py::test_spam[3]
failed test tests/test_spam.py::test_spam[4]
failed test tests/test_spam.py::test_eggs

请注意,
MyReporter.short\u test\u summary()
的上述impl不完整,仅用于演示目的!有关参考信息,请查看。

谢谢您的精彩回答!我能够用
report.nodeid
edit删除文件路径,这太完美了。一个问题tho,TerminalReporter被标记为
@final
,Pylance立即对此表示不满。如果我不能子类化,我不确定如何实现自己的TR,除非我从头开始重做整件事。@Isaahshiner这很不幸-看起来更改是在中引入的,所以6.1及以上版本受到影响。在我看来,这是一个值得怀疑的决定,例如,
pytestsugar
完全是围绕着对reporter进行子类化而建立的。无论如何,它只适用于类型检查器,并且在运行时被忽略,所以子类化不应该有任何问题;我会忽略这个警告。
========================== short test summary info ===========================
failed test tests/test_spam.py::test_spam[0]
failed test tests/test_spam.py::test_spam[1]
failed test tests/test_spam.py::test_spam[2]
failed test tests/test_spam.py::test_spam[3]
failed test tests/test_spam.py::test_spam[4]
failed test tests/test_spam.py::test_eggs