Pythonic方法测试属性?

时间:2016-07-30 00:56:45

标签: python unit-testing oop mocking pytest

我遇到了使用@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)模拟对象然后对属性/属性执行测试?

1 个答案:

答案 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