Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何在py.test终结器中打印内容_Python_Unit Testing_Pytest - Fatal编程技术网

Python 如何在py.test终结器中打印内容

Python 如何在py.test终结器中打印内容,python,unit-testing,pytest,Python,Unit Testing,Pytest,我正在测试一个写入日志文件的函数(它是否写入日志文件并不重要,它可以做任何事情,这正是产生这个问题的原因) 大概是这样的: def do_stuff(): with open('/tmp/mylogs.txt', 'a') as f: f.write(str(time.time())) f.write(' stuff done! \n') return 42 def test_doing_stuff(watch_logs): assert

我正在测试一个写入日志文件的函数(它是否写入日志文件并不重要,它可以做任何事情,这正是产生这个问题的原因)

大概是这样的:

def do_stuff():
    with open('/tmp/mylogs.txt', 'a') as f:
        f.write(str(time.time()))
        f.write(' stuff done! \n')
    return 42
def test_doing_stuff(watch_logs):
    assert do_stuff() == 42
    assert do_stuff() == 43
@pytest.fixture()
def watch_logs(request):
    with open('/tmp/mylogs.txt') as f:
        log_before = f.read()

    def get_new_logs():
        with open('/tmp/mylogs.txt') as f:
            log_after = f.read()
            return log_after.replace(log_before, '')

    return get_new_logs
我可以这样测试它:

def do_stuff():
    with open('/tmp/mylogs.txt', 'a') as f:
        f.write(str(time.time()))
        f.write(' stuff done! \n')
    return 42
def test_doing_stuff(watch_logs):
    assert do_stuff() == 42
    assert do_stuff() == 43
@pytest.fixture()
def watch_logs(request):
    with open('/tmp/mylogs.txt') as f:
        log_before = f.read()

    def get_new_logs():
        with open('/tmp/mylogs.txt') as f:
            log_after = f.read()
            return log_after.replace(log_before, '')

    return get_new_logs
出于调试目的,当测试失败时,我希望能够打印出日志的新内容——我可以制作一个类似于以下内容的装置:

def do_stuff():
    with open('/tmp/mylogs.txt', 'a') as f:
        f.write(str(time.time()))
        f.write(' stuff done! \n')
    return 42
def test_doing_stuff(watch_logs):
    assert do_stuff() == 42
    assert do_stuff() == 43
@pytest.fixture()
def watch_logs(request):
    with open('/tmp/mylogs.txt') as f:
        log_before = f.read()

    def get_new_logs():
        with open('/tmp/mylogs.txt') as f:
            log_after = f.read()
            return log_after.replace(log_before, '')

    return get_new_logs
很好-现在我可以在测试的任何时候检查日志内容:

def test_doing_stuff(watch_logs):
    assert do_stuff() == 42
    print(watch_logs())
    assert do_stuff() == 43
    print(watch_logs())
嗯-啊,但是第二次打印不起作用,是在测试失败之后

如果我的测试夹具总是在测试结束时打印出日志呢?然后pytest的stdout捕获将在失败时向我显示,但在通过时不会显示

@pytest.fixture()
def watch_logs(request):
    with open('/tmp/mylogs.txt') as f:
        log_before = f.read()

    def get_new_logs():
        with open('/tmp/mylogs.txt') as f:
            log_after = f.read()
            return log_after.replace(log_before, '')

    def print_new_logs():
        print('~' * 20 + ' logs ' + '~' * 20)
        print(get_new_logs())
        print('~' * 50)
    request.addfinalizer(print_new_logs)

    return get_new_logs
哦,但这不起作用,因为pytests的日志捕获不会在测试终结器期间发生

所以问题是:如何制作一个可以打印内容的测试终结器


这里有一个没有(不相关的)写入日志文件内容的超简单要点:

没有文档化或干净的方法来实现它,但这里有一个技巧:

# conftest.py

def pytest_runtest_call(item):
    if hasattr(item, "_request"):
        if hasattr(item._request, "_addoutput_on_failure"):
            item._request._addoutput_on_failure()

# test_x.py
import pytest

@pytest.fixture
def print_on_fail(request):
    def add():
        print ("test failed")
    request._parent_request._addoutput_on_failure = add

def test_doing_stuff(print_on_fail):
    assert False
我们可以考虑一个合适的
request.addcall\u on\u失败(回调)
API


使
yield\u fixture
案例工作需要一些内部重构,这可能是非常重要的

多亏了霍尔格本人的帮助(谢谢@hpk42!),我得到了一些有用的东西。只是稍微有点神奇

解决方案是使用一个名为
pytest\u pyfunc\u call
的py.test钩子,以及一个名为
hookwrapper
的修饰符。它们为我提供了一种方法,可以在测试运行之前和之后钩住一些代码,但也不会受到stdout劫持的影响

我们在conftest.py中定义了一个新函数:

现在,如果pytest发现任何使用
watch_logs
fixture的测试,它将在测试运行后打印其输出


完整示例:

差不多。我需要在测试主体完成后运行代码(以便它从日志文件中选择相关内容)。将有一个关于插件api窥探。。。但是我认为问题在于stdout capture在拆卸时停止工作?上面的
add
函数是在测试函数的主体之后和拆卸之前调用的。是的。如果我将一个
print(“testing”)
添加到
test\u doing\u stuff
中,我会在输出中得到“test failed”,然后是“testing”。通过将
time.time()
添加到打印中进行检查,确认在
add
print.aha>之后进行测试打印!如果我真的在try/except中调用
item.runtest()
,并将
\u addoutput
放入finally块中,它就会工作。使用pytest-2.8,这些机制将得到更好的记录。