I have got the following very simple functions and tests:
from feedback import error_msg, info_msg, warn_msg
import pytest
def test_message_info(capsys):
@info_msg
def message():
return "testmessage"
message()
assert capsys.readouterr().out == "INFO: testmessage\n"
def test_message_error(capsys):
@error_msg
def message():
return "testmessage"
message()
assert capsys.readouterr().out == "ERROR: testmessage\n"
def test_message_warning(capsys):
@warn_msg
def message():
return "testmessage"
message()
assert capsys.readouterr().out == "WARN: testmessage\n"
I know there are probably ways reduce these tests to a single test with a fixture or pytest.mark.parametrize
, but I can not get my head around how to solve this. Does anyone know how to do this with a decorator?
I'd use @pytest.mark.parametrize
:
import pytest
import functools
# Quickly reimplement the `feedback` decorators, so that this
# example will be runnable. These lines aren't important if
# you're just interested in the answer to the question at hand.
def log_msg(message):
def decorate(f):
@functools.wraps(f)
def wrapper(*args, **kwargs):
out = f(*args, **kwargs)
print(f'{message}: {out}')
return wrapper
return decorate
info_msg = log_msg('INFO')
error_msg = log_msg('ERROR')
warn_msg = log_msg('WARN')
# Make a parametrized test:
@pytest.mark.parametrize(
'decorator, expected', [
(info_msg, 'INFO: testmessage\n'),
(error_msg, 'ERROR: testmessage\n'),
(warn_msg, 'WARN: testmessage\n'),
],
)
def test_decorators(decorator, expected, capsys):
@decorator
def message():
return "testmessage"
message()
assert capsys.readouterr().out == expected
(Edited to make runnable, and to fix some bugs.)