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.
Here's the code:
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())
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
works great!
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?
What would you do?
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
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.
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)
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)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.