测试驱动开发:编写私有/受保护变量的测试

时间:2010-06-15 21:18:09

标签: unit-testing variables tdd private protected

我正在学习TDD,我对私有/受保护变量有疑问。我的问题是:如果我要测试的函数是在私有变量上运行,我应该如何测试它?

以下是我正在使用的示例:

我有一个名为Table的类,它包含一个名为internalRepresentation的实例变量,它是一个2D数组。我想创建一个名为multiplyValuesByN的函数,它将2D数组中的所有值乘以参数n

所以我为它编写测试(在Python中):

def test_multiplyValuesByN (self):  
    t = Table(3, 3) # 3x3 table, filled with 0's
    t.set(0, 0, 4) # Set value at position (0,0) to 4
    t.multiplyValuesByN(3)

    assertEqual(t.internalRepresentation, [[12, 0, 0], [0, 0, 0], [0, 0, 0]])

现在,如果我将internalRepresentation设为私有或受保护,则此测试将无效。我应该如何编写测试,以便它不依赖于internalRepresentation,但仍然在调用multiplyValuesByN后测试它看起来是否正确?

4 个答案:

答案 0 :(得分:10)

您不应该依赖于对象的内部表示。这就是它被标记为私有或受保护的原因。考虑调用t.multiplyValuesByN(3)时对t的可观察变化。然后,测试你可以观察到的东西。

def test_multiplyValuesByN (self):  
    t = Table(3, 3) # 3x3 table, filled with 0's
    t.set(0, 0, 4) # Set value at position (0,0) to 4
    t.multiplyValuesByN(3)

    assertEqual(t.get(0,0), 12)

答案 1 :(得分:3)

如果它是内部的,那么它就是课外的nobodys业务,包括测试。

在TDD中,您正在设计类的API,未来的客户端也只能看到类的可观察行为。

我知道这说起来容易做起来难。

在测试中,您经常会看到一种模式重新启动:设置 - 操作 - 检查( - 拆解)

设置阶段负责使对象处于先决条件状态。

检查阶段应通过类的可观察行为来验证后置条件。如果它永远不会出现,那么存储隐形状态是没有意义的。

答案 2 :(得分:3)

其他人已经发布了很好的答案,但恕我直言没有强调一件事:设计方面(虽然彼得蒂勒曼斯提到它)。所以我对此加了一点解释。

在进行TDD时,您正在有效地测试API的设计以及实现。如果您发现方法调用的结果很难或无法从外部看到,这几乎总是表明您的类接口设计不好。如果很难为你的课程编写测试,通常很难在现实生活中使用它 - 你的单元测试实际上是你班级的第一批客户。因此,如果您发现测试用例在使用类接口时遇到困难,您应该考虑返回并重新设计API以使其更易于使用(如果可能的话,不要破坏封装)。

答案 3 :(得分:0)

不要测试私有变量/状态。您的测试应确认被测单元符合其规范,该规范由其接口决定。因此,您的测试应根据测试单元的输入进行编写,并验证输出是否符合您的预期。

您希望能够更改被测设备的实施(例如,效率原因),并确认其按预期工作。因此,检查私有州会在这种情况下造成困难。