无法在装饰器中捕获 pytest 的结果 [英] unable to capture results of pytest in decorator

查看:48
本文介绍了无法在装饰器中捕获 pytest 的结果的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的 pytest 测试装饰器会在函数被调用后立即退出装饰器.如果我使用 python 而不是 pytest 运行文件,效果会很好.

my decorator for pytest tests exits the decorator as soon as the function is called. Works great if I run the file with python instead of pytest.

代码如下:

def dec(func):
    def wrapper(*args, **kwargs):
        print('do some stuff')
        result = func(*args, **kwargs)
        print('ran function')
        return False if result else return True
    return wrapper

@dec
def test_something_is_not_true():
    return False # assert False

@dec
def test_something_is_true():
    return True # assert True


print(test_something_is_not_true())
print(test_something_is_true())

我用python运行文件的结果如下:

the results of this when I run the file with python are as follows:

C:\tests> python test.py
do some stuff
ran function
True
do some stuff
ran function
False

效果很好!

但是当我用 pytest 运行它时,它停在 result = func(*args, **kwargs) 行并且从不执​​行 print('ran function') 线:

but when I run it with pytest it stops at the result = func(*args, **kwargs) line and never executes the print('ran function') line:

C:\tests>pytest test.py
============================= test session starts =============================
platform win32 -- Python 3.6.4, pytest-3.3.2, py-1.5.2, pluggy-0.6.0
rootdir: C:\, inifile:
plugins: metadata-1.7.0, jira-0.3.6, html-1.19.0
collected 2 items

test.py F.                                                               [100%]

================================== FAILURES ===================================
_________________________ test_something_is_not_true __________________________

args = (), kwargs = {}

    def wrapper(*args, **kwargs):
        print('do some stuff')
>       result = func(*args, **kwargs)

test.py:20:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

    @dec
    def test_something_is_not_true():
>       assert False
E       assert False

test.py:31: AssertionError
---------------------------- Captured stdout call -----------------------------
do some stuff
===================== 1 failed, 1 passed in 0.11 seconds ======================

如您所见,装饰器函数并没有真正做任何事情……但是如果我可以让它工作,那么我可以查看该函数中的测试是否通过,如果是,则根据结果执行一些额外的逻辑测试的通过或失败.也许使用装饰器来完成捕获测试的输出不是最好的方法?

As you can see, the decorator function is not really doing anything... but if I could get that to work then I could see if the test passed in that function and if so, perform some extra logic based on the result of the pass or fail of the test. Perhaps using Decorators to accomplish capture the output of a test isn't the best way to do it?

你会怎么做?

推荐答案

如果你需要在测试前后执行代码,这在 fixture.示例:

If you need to execute code before and after the test, this is done in a fixture. Example:

import pytest

@pytest.fixture
def wrapper(request):
    print('\nhere I am before the test')
    print('test function name is', request.node.name)
    print('test file is located under', request.node.fspath)
    yield
    print('\nand here I am after the test')


@pytest.mark.usefixtures('wrapper')
def test_spam_good():
    assert True

@pytest.mark.usefixtures('wrapper')
def test_spam_bad():
    assert False

如您所见,这比编写自定义装饰器强大得多.由于 pytest 非常擅长围绕测试进行元编程,您可能需要的很多东西已经存在,您只需要知道如何访问它.pytest 文档 包含许多适合初学者的示例和食谱.

As you can see, this is much more powerful than writing custom decorators. As pytest is very good at metaprogramming around tests, a lot of stuff you may need is already there, you just need to know how to access it. pytest docs contain many examples and recipes for beginners.

如果您需要夹具中的测试结果,文档中有一个配方:使测试结果信息在夹具中可用.在项目根目录下创建一个conftest.py文件,内容如下:

If you need the test outcome in the fixture, there is a recipe for that in the docs: Making test result information available in fixtures. Create a file conftest.py in the project root dir with the following content:

import pytest


@pytest.hookimpl(tryfirst=True, hookwrapper=True)
def pytest_runtest_makereport(item, call):
    # execute all other hooks to obtain the report object
    outcome = yield
    rep = outcome.get_result()

    # set a report attribute for each phase of a call, which can
    # be "setup", "call", "teardown"

    setattr(item, "rep_" + rep.when, rep)

现在您可以通过自定义夹具中的 request 夹具访问测试结果:

Now you can access the test outcome via request fixture in your custom fixtures:

@pytest.fixture
def something(request):
    yield
    # 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)

这篇关于无法在装饰器中捕获 pytest 的结果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆