I have been trying lately to learn a lot in the best methods for testing modules. Most of them make sense, but there is something that is often overlooked and / or poorly explained: how should one test element decorate functions?
Suppose I have this code:
def stringify(func): @wraps(func) def wrapper(*args): return str(func(*args)) return wrapper class A(object): @stringify def add_numbers(self, a, b): """ Returns the sum of `a` and `b` as a string. """ return a + b
I obviously can write the following tests:
def test_stringify(): @stringify def func(x): return x assert func(42) == "42" def test_A_add_numbers(): instance = MagicMock(spec=A) result = A.add_numbers.__wrapped__(instance, 3, 7) assert result == 10
This gives me 100% coverage: I know that any function that is decorated with stringify() gets its result as a string, and I know that the undecorated A.add_numbers() function returns the sum of its arguments. Thus, in terms of transitivity, the issued version of A.add_numbers() should return the sum of its argument as a string. Everything seems good!
However, I'm not quite happy with this: my tests, as I wrote, can still pass if I use a different decorator (which does something else, multiply the result by 2 instead of casting to str ). My A.add_numbers function A.add_numbers not be correct, but the tests will pass anyway. Not surprising.
I could test the decorated version of A.add_numbers() , but then I would try everything, since my decorator was already tested for one.
It seems that I missed something. What is a good strategy for unit tests of decorated functions?