ere*_*eOn 12 python unit-testing
我最近尝试过对单元测试最佳实践进行大量训练.其中大部分内容都非常有意义,但有一些内容经常被忽视和/或解释得很糟糕:一个单元测试如何装饰功能?
我们假设我有这个代码:
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
Run Code Online (Sandbox Code Playgroud)
我显然可以写下面的测试:
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
Run Code Online (Sandbox Code Playgroud)
这给了我100%的覆盖率:我知道任何被装饰的函数都stringify()将其结果作为字符串获取,并且我知道未修饰的A.add_numbers()函数返回其参数的总和.因此,通过传递性,装饰版本A.add_numbers()必须返回其参数的总和,作为字符串.一切都好看!
但是我对此并不完全满意:我的测试,因为我写的它们仍然可以通过,如果我要使用另一个装饰器(做其他事情,比如将结果乘以2而不是转换为a str).我的功能A.add_numbers不再正确,但测试仍然会通过.不太棒.
我可以测试装饰版本,A.add_numbers()但随后我会推翻,因为我的装饰器已经过单元测试.
感觉我在这里遗漏了一些东西.单元测试装饰功能的好策略是什么?
我最终将我的装饰者一分为二。所以,而不是:
def stringify(func):
@wraps(func)
def wrapper(*args):
return str(func(*args))
return wrapper
Run Code Online (Sandbox Code Playgroud)
我有:
def to_string(value):
return str(value)
def stringify(func):
@wraps(func)
def wrapper(*args):
return to_string(func(*args))
return wrapper
Run Code Online (Sandbox Code Playgroud)
这允许我稍后to_string在测试装饰函数时简单地模拟。
显然,在这个简单的示例案例中,它可能看起来有点矫枉过正,但是当在装饰器上使用时,它实际上做了一些复杂或昂贵的事情(比如打开与数据库的连接,或者其他什么),能够模拟它是一件非常好的事情。
| 归档时间: |
|
| 查看次数: |
4040 次 |
| 最近记录: |