2010-06-15 87 views
3

我正在学习TDD,并且对私有/受保护变量有疑问。我的问题是:如果我想测试的函数是对一个私有变量进行操作,我应该如何测试它?测试驱动开发:为私有/受保护变量编写测试

这里是我的工作的例子:

我有一个称为Table类,它包含称为internalRepresentation的实例变量是2D阵列。我想创建一个名为multiplyValuesByN的函数,它将二维数组中的所有值乘以参数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后仍然测试它看起来正确?

回答

10

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

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) 
0

不要测试私有变量/状态。您的测试应确认被测单元符合其规格,并且该规格取决于其界面。所以你的测试应该根据你的测试单元的输入来写,并且验证输出是否符合你的期望。

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

3

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

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

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

在测试你经常看到一个模式reoccuring:设置 - 经营 - 检查( - 拆解)

设置阶段负责把对象的先决条件状态。

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

+0

...也被称为Arrange-Act-Assert(但没有用于拆解的一致性匹配 - 猜测这是一件好事,它没有多少用处!) – 2010-06-16 14:31:35

+0

是的,这就是为什么我把它放在括号内。这是有时需要的那些实际的东西之一,但不适合理论。我喜欢3-A的一致性。之前没有听说过,谢谢! – 2010-06-16 16:38:11

3

其他人已经发布了很好的答案,但恕我直言,未能强调一件事:设计方面(尽管彼得Tillemans提到它)。所以我对此加了一点解释。

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