我正在学习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
后测试它看起来是否正确?
答案 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)
不要测试私有变量/状态。您的测试应确认被测单元符合其规范,该规范由其接口决定。因此,您的测试应根据测试单元的输入进行编写,并验证输出是否符合您的预期。
您希望能够更改被测设备的实施(例如,效率原因),并确认其按预期工作。因此,检查私有州会在这种情况下造成困难。