pytest自定义断言,如何获取traceb

2024-10-03 19:27:20 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个简单的测试代码:

试验_断言.py在

import helper


def test_assert():
    assert helper.find_event(helper.HelperEvents("event","this is info")) is True

在助手.py在

^{pr2}$

这会给我一个这样的断言错误:

    def test_assert():
>       assert helper.find_event(helper.HelperEvents("event","this is info")) is True
E       AssertionError: assert False is True
E        +  where False = <function find_event at 0x158c9b0>(<test_asserts.helper.HelperEvents instance at 0x157d488>)
E        +    where <function find_event at 0x158c9b0> = helper.find_event
E        +    and   <test_asserts.helper.HelperEvents instance at 0x157d488> = <class test_asserts.helper.HelperEvents at 0x1670188>('event', 'this is info')
E        +      where <class test_asserts.helper.HelperEvents at 0x1670188> = helper.HelperEvents

test_assert.py:5: AssertionError

但我真的想把它简化成这样: AssertionError:事件:事件信息:在列表中未找到此信息

为此,我创建了一个init.py文件

import pytest
pytest.register_assert_rewrite('test_asserts')

还有一个conftest.py文件:

import pytest


@pytest.hookimpl(tryfirst=True)
def pytest_assertrepr_compare(op, left, right):
    print "Left:", left
    print "op:", op
    print "Right:", right
    return [str(left), op, str(right)]

我得到了以下结论:

    def test_assert():
>       assert helper.find_event(helper.HelperEvents("event","this is info")) is True
E       assert False
E         is
E         True

test_assert.py:5: AssertionError

当我只看到find_事件调用的结果时,如何从事件中提取信息?在


Tags: pytestinfohelpereventtruepytestis
1条回答
网友
1楼 · 发布于 2024-10-03 19:27:20

所以我最终实现了pytest_runtest_makereport的钩子。 我重用了pytests实现中的代码,并用我自己的自定义assert表示对其进行了扩展。 看起来像这样:

import pytest
from _pytest._code.code import ExceptionInfo
from _pytest.outcomes import skip
from _pytest._code.code import ReprTraceback, ReprEntry, ReprFileLocation, Traceback
from _pytest.runner import TestReport


@pytest.hookimpl(tryfirst=True)
def pytest_runtest_makereport(item, call):
    when = call.when
    duration = call.stop - call.start
    keywords = dict([(x, 1) for x in item.keywords])
    excinfo = call.excinfo
    sections = []
    if not call.excinfo:
        outcome = "passed"
        longrepr = None
    else:
        if not isinstance(excinfo, ExceptionInfo):
            outcome = "failed"
            longrepr = excinfo
        elif excinfo.errisinstance(skip.Exception):
            outcome = "skipped"
            r = excinfo._getreprcrash()
            longrepr = (str(r.path), r.lineno, r.message)
        else:
            outcome = "failed"
            if call.when == "call":
                longrepr = custom_excinfo_repr(excinfo) # This creates my custom assert representation
            else:  # exception in setup or teardown
                longrepr = item._repr_failure_py(excinfo,
                                                 style=item.config.option.tbstyle)
    for rwhen, key, content in item._report_sections:
        sections.append(("Captured %s %s" % (key, rwhen), content))
    if longr


def beautify_exc_output(lines):
    out = []
    if any("helper.find_event" in s for s in lines):
        out = parseAssert(lines)
    return out


def parseAssertion(lines):
    assertionType = ""
    args = []
    out = []
    compare = []

    # extract data from input
    for line in lines:
        line = line.strip("+ ")
        if "AssertionError" in line:
            assertionType = line[line.find("assert"):]
            compare = [int(s) for s in assertionType.split() if s.isdigit()]  # Check if assertion was an integer compare
        if "HelperEvents" in line and "where" not in line:
            content = line[line.find("(")+1:line.find(")")]  # Find content of event
            args = [x.strip(" '") for x in content.split(",")]  # split in to args

    # Generate output
    if len(args) > 1 and len(assertionType) > 0:
        Indent = "    "
        out.append("Assertion error in HelperEvents:")
        out.append("###############################################################")
        if len(compare) == 2:
            out.append("  Expected {0} times {1} but got {2} times".format(compare[1], args[0], compare[0]))
        out.append("  " + GetAssertionEvent(assertionType))
        out.append(Indent + "Event: {}".format(args[0]))
        out.append(Indent + "Info: {}".format(args[1]))
        out.append("###############################################################")
    return out


def GetAssertionEvent(AssertionType):
    if "assert not False" in AssertionType or \
            "assert True is False" in AssertionType or \
            "assert True" in AssertionType:
        return "Unexpected event has been received"
    elif "assert False" in AssertionType or \
            "assert False is True" in AssertionType:
        return "Expected event was not received"
    else:
        return AssertionType

所有这些代码都放在conftest.py马上。 如果断言是一个不能被实现识别的类型,它将从my hook返回None,这将使pytest使用默认实现。在

相关问题 更多 >