我遇到了使用@property
装饰器为类属性编写单元测试的问题。我使用优秀的py.test软件包进行测试,肯定更喜欢坚持使用它,因为它很容易设置灯具。我编写单元测试的代码如下所示:
class Foo(object):
def __init__(self, fizz, buzz, (and many more...)):
self.fizz = fizz
self.buzz = buzz
self.is_fizzing = #some function of fizz
self.is_fizz_and_buzz = fizz and buzz
...
@property
def is_bar(self):
return self.is_fizz_and_buzz and self.buzz > 5
@property
def foo_bar(self):
# Note that this property uses the property above
return self.is_bar + self.fizz
# Long list of properties that call each other
为某个属性编写单元测试时会出现问题,该属性使用多个其他属性,有时在最多四个属性的长链中。对于每个单元测试,我需要确定需要设置哪些输入,更糟糕的是,这些输入可能与测试该特定方法的功能无关。结果,我最终测试了其中一些"属性所需的更多案例。"
我的直觉告诉我,如果这些实际上是"属性"他们不应该进行这么长时间的计算,需要进行测试。也许最好将实际方法(使它们成为类方法)分开并编写调用这些类方法的新属性。
当前代码的另一个问题 - 如果我错了,请纠正我 - 每次调用属性时(大多数属性被称为很多)都会重新计算属性。这似乎非常低效,可以用新属性修复like this。
测试属性是否有意义?换句话说,属性本身应该在属性中计算还是应该只设置?如上所述重写代码似乎是 unpythonic 。为什么甚至首先拥有房产?如果属性应该如此简单而不需要测试,为什么不在init中定义属性?
对不起,如果这些都是愚蠢的问题。我对python仍然相当新。
修改/更新: 是否可以(简单/ pythonic)模拟对象然后对属性/属性执行测试?
答案 0 :(得分:0)
执行imo的最简单方法是仅测试属性,例如foo_bar
,作为使用其函数成员的常规方法,例如foo_bar.func
,它是@property
自动提供的。
对我来说,使用pytest和unittest.mock,这意味着当foo_bar
是正常的非财产方法时,不要执行以下操作:
class TestFoo:
def test_foo_bar(self):
foo_mock = mock.create_autospec(Foo)
# setup `foo_mock` however is necessary for testing
assert Foo.foo_bar(foo_mock) == some_value
我将更改最后一行来做到这一点:
assert Foo.foo_bar.func(foo_mock) == some_value
如果您需要在过程中存根/模拟其他属性(例如Foo.is_bar
),请查看unittest.mock.PropertyMock。