3

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

这是我正在使用的示例:

我有一个名为的类Table,它包含一个名为的实例变量internalRepresentation,它是一个二维数组。我想创建一个函数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

4 回答 4

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)
于 2010-06-15T21:21:41.370 回答
3

如果它是内部的,那么它在课堂之外是没有人的事,包括测试。

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

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

在测试中,您经常会看到重复出现的模式:设置 - 操作 - 检查(- 拆卸)

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

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

于 2010-06-15T21:27:23.263 回答
3

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

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

于 2010-06-16T09:34:56.220 回答
0

不要测试私有变量/状态。您的测试应确认被测单元符合其规范,并且该规范由其接口确定。所以你的测试应该根据你的测试单元的输入来编写,并验证输出是否符合你的期望。

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

于 2010-06-15T21:26:16.320 回答