def decorator(some_function):
def wrapper(*args, *kwargs):
# do some stuff before some_function is called
some_function()
# do some stuff after some_function is called
return wrapper@decorator
def my_awesome_function():
print "hello world"def validate_ints(fn):
def wrapper(a, b, *args, *kwargs):
try:
a = int(a)
b = int(b)
except ValueError, exc:
logger.info("Both parameters must be an integer")
raise exc
return some_function(a, b)
return wrapper@validate_ints
def adding(a, b):
return a + bWhat if we want our decorators to have their own parameters?
def validate_numbers(num_type):
def outter_wrapper(fn):
def inner_wrapper(a, b, *args, *kwargs):
try:
a = num_type(a)
b = num_type(b)
except ValueError, exc:
logger.error("Both parameters must be of type {}".format(
type(num_type)))
raise exc
return some_function(a, b)
return inner_wrapper
return outter_wrapper@validate_numbers(int)
def adding(a, b):
return a + b
@validate_numbers(float)
def division(a, b):
return a / bdef decorator(some_function, *args, **kwargs):
def wrapper(*args, *kwargs):
# do some stuff before some_function is called
some_function()
# do some stuff after some_function is called
return wrapper
def decorator_with_parms(param1, *args, **kwargs):
def outter_wrapper(fn):
def inner_wrapper(arg1, *args, *kwargs):
# do some stuff before some_function is called
some_function(arg1, *args, **kwargs)
# do some stuff after some_function is called
return inner_wrapper
return outter_wrapper"But my imports explicitly reference my function and not the decorator...how does this work!?!"
So what's so special about writing tests against decorated methods?
What happens if we would like to write unit tests for a method we have wrapped with a decorator?
def decorator(some_function, *args, **kwargs):
def wrapper(*args, *kwargs):
if not check_authentication():
raise NotAuthenticatedError
return some_function()
return wrapper
@decorator
def hello_world():
return "Hello world!"from some.place import hello_world
class TestStuff(TestCase):
def test_results(self):
self.assertEqual("Hello world!", hello_world())This test will fail and raise a "NotAuthenticatedError" exception.
Before importing the module you want to test that is wrapped with a decorator:
The secret to testing/mocking methods that have been decorated lies in understanding:
Helpful resources about decorators