pytest夹具用于接管错误报告

1 投票
1 回答
1479 浏览
提问于 2025-04-20 09:56

我正在写一个小工具,用来进行回归测试。被测试的函数没有任何断言语句,但它会产生一些输出,这些输出会和之前记录的正确输出进行比较。

这是一个简化的代码片段,展示我正在做的事情:

@pytest.yield_fixture()
def regtest(request):

    fp = cStringIO.StringIO()

    yield fp

    reset, full_path, id_ = _setup(request)
    if reset:
        _record_output(fp.getvalue(), full_path)
    else:
        failed = _compare_output(fp.getvalue(), full_path, request, id_)
        if failed:
            pytest.fail("regression test %s failed" % id_, pytrace=False)

总体来说,我的方法是有效的,但我想改善错误报告,让工具能够显示测试失败,而不是测试函数本身:因为这个实现总是会打印一个 .,这是因为被测试的函数没有抛出任何异常,然后如果在最后一行调用了 pytest.fail,就会多打印一个 E

所以我想要的是抑制被测试函数触发的 . 输出,让我的工具代码输出合适的字符。

更新
我已经能够改善输出,但在测试运行时,输出中仍然有太多的 "."。你可以在 https://pypi.python.org/pypi/pytest-regtest 找到它,代码库在 https://sissource.ethz.ch/uweschmitt/pytest-regtest/tree/master

抱歉发了链接,但文件现在有点大了。

解决方案

我想出了一个解决方案,通过实现一个钩子来处理回归测试的结果。代码(简化后)是:

@pytest.yield_fixture()
def regtest(request):
    fp = cStringIO.StringIO()
    yield fp

@pytest.hookimpl(hookwrapper=True)
def pytest_runtest_call(item):
    try:
        outcome = yield
    except Exception:
        raise
    else:
        # we only handle regtest fixture if no other other exception came up during testing:
        if outcome.excinfo is not None:
            return

        regtest = item.funcargs.get("regtest")
        if regtest is not None:
            _handle_regtest_result(regtest)

_handle_regtest_result 要么存储记录的值,要么进行适当的检查。这个插件现在可以在 https://pypi.python.org/pypi/pytest-regtest 找到。

1 个回答

0

你把两件事搞混了:一个是测试的准备工作(也就是设置测试的条件),另一个是你期望的行为 _compare_output(a, b)。你可能想要的是类似下面这样的东西:

import pytest

@pytest.fixture()
def file_fixture():
    fp = cStringIO.StringIO()
    return fp.getvalue()

@pytest.fixture()
def request_fixture(request, file_fixture):
    return _setup(request)

def test_regression(request_fixture, file_fixture):
    reset, full_path, id_ = request_fixture
    if reset:
        _record_output(file_fixture, full_path)
    else:
        failed = _compare_output(file_fixture, full_path, request, id_)
        assert failed is True, "regression test %s failed" % id_

撰写回答