如何修改特定测试的故障报告

时间:2014-02-15 13:50:39

标签: python pytest

我有自定义夹具,它在测试期间收集有关DB的查询信息,如果测试失败,使用该夹具,我想添加夹具收集的信息进行报告。我怎么能这样做?

更新

它看起来如何:

from contextlib import contextmanager
import db
import pytest

def make_cursor_handler():
    ...
    return cursor_handler, list_with_log

@contextmanager
def wrap_cursor():
    old_handler = db.cursor_handler
    db.cursor_handler, list_with_log = make_cursor_handler()
    yield list_with_log
    db.cursor_handler = old_handler

@pytest.yield_fixture
def cursor_fixture():
    with wrap_cursor() as log:
        yield log #How would I print it inside error report without including it in assert message?

3 个答案:

答案 0 :(得分:4)

您可以使用pytest-capturelog捕获测试中写入的所有日志消息,包括在安装和拆卸期间。因此,无论你记录什么都是报告的一部分,这可能非常有用(我们确实在我雇用的公司中使用它;虽然我们使用鼻子,它处理它而没有任何插件AFAIK)。

pip install pytest-capturelog

然后你可以在测试期间的任何地方记录消息(设置,拆解,固定装置,辅助函数),pytest-capturelog应该处理它:

import logging

log = logging.getLogger(__name__)

def setup_function(function):
    log.info("setup log message")

def test_it():
    log.info("test log message")
    assert False

结果(见Captured log):

==================== test session starts =====================
platform linux2 -- Python 2.7.4 -- py-1.4.20 -- pytest-2.5.2
plugins: capturelog
collected 1 items 

file.py F

========================== FAILURES ==========================
__________________________ test_it ___________________________

    def test_it():
        log.info("test log message")
>       assert False
E       assert False

file.py:10: AssertionError
------------------------ Captured log ------------------------
file.py                      6 INFO     setup log message
file.py                      9 INFO     test log message
================== 1 failed in 0.01 seconds ==================

答案 1 :(得分:1)

您是否可以使用其他信息调用报告标题,或者让自定义夹具打印其他信息?它看起来就像是他们在pytest.org上给出的例子。

报告标题代码here

def pytest_report_header(config):
    return "Additional Information here"

灯具代码here

如果您发布代码,我认为我们可以更好地排查问题。

@pytest.fixture
def something(request):
    def fin():
        # request.node is an "item" because we use the default
        # "function" scope
        if request.node.rep_setup.failed:
            print "setting up a test failed!", request.node.nodeid
        elif request.node.rep_setup.passed:
            if request.node.rep_call.failed:
                print "executing test failed", request.node.nodeid
    request.addfinalizer(fin)

答案 2 :(得分:0)

打印有效,但不是很灵活。如果您真的想要隔离测试的输出并且不想看到任何其他内容,那就太棒了。如果您对查看应用程序的各种包和组件(django,httplib等)中的错误感兴趣,那么您希望使用日志记录。

要在没有插件的情况下获取测试报告中的日志输出,只需将日志记录设置为输出到stdout / stderr;这基本上将日志调用转换为超级电源打印调用。然后,如果你运行pytest 而不使用-s开关,输出将被添加到测试结果中。

以下是配置日志记录的方法;确保尽早执行!

import logging
from sys import stdout, stderr

# this is our root logger, give it the name you want
log = logging.getLogger("myScript")  

# prevents adding the same handlers over and over again if your script is read multiple times
if not len(log.handlers):
    log.setLevel(logging.DEBUG)
    # we are setting a file log, and also redirecting to stdout/stderr
    logger_file_handler = logging.FileHandler('myScript.debug.log')
    console_flow_handler = logging.StreamHandler(stdout)
    console_error_handler = logging.StreamHandler(stderr)
    # set their levels. file gets all, console gets info and up, stderr gets warnings and up
    logger_file_handler.setLevel(logging.DEBUG)
    console_flow_handler.setLevel(logging.INFO)
    console_error_handler.setLevel(logging.WARNING)
    # ok, add them!
    log.addHandler(logger_file_handler)
    log.addHandler(console_flow_handler)
    log.addHandler(console_error_handler)
    # don't propagate messages to parent (root), else we get duplicates - this may or may not fit your situation
    log.propagate = False

然后在你的测试中,你可以这样做:

import logging; log = logging.getLogger("myScript.TestName")

def test_something():
    log.debug("This only goes into the log file")
    log.info("This will be printed to console too")
    log.warning("This goes to stdout and stderr - pytest will print stderr into its own section so that you can see them quickly")
    assert 0  # if it fails, you get the logs. if it pass, you get nothing.