不测试公共方法

时间:2013-10-07 10:16:45

标签: ruby-on-rails ruby tdd

我从POODR等书籍中看到的关于TDD的一般建议是不测试私有方法。我们的想法是调用私有方法的公共方法将被测试,并且应该足以验证私有方法。

这是有道理的但是私有方法是多个“层”深层的情况呢?这是我的意思的一个人为的例子:

public

# test this method
def foo
  private1
end

private

def private1
  private2
end

def private2
  private3
end

def private3
  # does stuff
end

我没有真实世界的例子可以分享,但在这种情况下,仅仅测试公共方法foo还是不错的吗?或者像这样构造的代码指向可能更深层次的问题?

5 个答案:

答案 0 :(得分:3)

这背后的想法是类的内部是该类的实现细节。

您的设计示例仅将foo的输出公开给用户。所以这是你的测试必须确保不变的唯一东西。

如果你用10个方法(例如foo)干掉整个类,只在内部使用一个方法,你就不希望看到任何测试因为你改为私有而中断。只要公共接口仍然有效,就不需要测试内部。

这背后的原理是封装。你不关心你的课在幕后做什么 - 因为你担心它可以在量子计算机上运行并将它的数据流发送给一个人在月球上进行计算 - 只要输出正确,您的用户就会看到正确的预期结果。

任何测试私有的尝试只会导致一旦您更改这些方法就会中断测试。 在很多情况下这很好,但是过度测试会让你花费更多的时间修复破坏的测试,而不是高效,所以这条规则主要是给你一些摆动空间。

当然这个建议总是取决于:如果你觉得这个方法很有用,你可能想为它编写测试。但是,这些测试大多是重复你已经为公共方法准备的测试。

答案 1 :(得分:1)

我仍然只测试#foo,因为它是其他对象依赖的唯一方法。如果你的测试“证明”foo做了它应该做的事情,那么调用多少私有方法来实现这一目标并不重要。

您可能会喜欢Sandy Metz的演讲,进一步说明测试技巧: http://www.youtube.com/watch?v=URSWYvyc42M

但我得到你的担忧。如果您对某个私有方法感到不安全,可以编写一些测试来对该方法更有信心,但不要浪费太多时间来维护这些测试。

假设您更改了一些实现细节,现在#private2的测试失败,但#foo的测试仍然是绿色,我不会花太多时间来修复#private2。 (换句话说,删除#private2的测试)

答案 2 :(得分:0)

我认为测试函数foo足以测试其他私有函数。我发现深层次的函数调用没有任何问题。作为一个单元的Foo函数应适用于所有断言。

答案 3 :(得分:0)

测试公共接口才有意义,因为您希望确保与代码的外部交互是安全的并且按预期工作,同时您希望保持合理的灵活性来更改实现而不更改测试。

如果您认为私有方法中包含的概念足够复杂或有趣,您可能希望将其转换为单独的类,创建新的公共接口并为其编写测试。 有很多建议可以帮助您确定何时清理诸如SOLID原则之类的内容

不要考虑编写测试或编写代码,不打算维护。

答案 4 :(得分:0)

我并不总是喜欢这本书。有时需求/要求也决定了您的方法。

几天前我遇到了这种情况。虽然我正在研究Java代码,而我的答案是基于Java的,但无论您考虑使用何种编程语言,它仍然可能仍然有用。

在尝试为现有(旧)巨大类(具有<40%的代码覆盖率)实现良好的代码覆盖时,我不得不编写几个测试用例,因此注意到了一些事情:

1)很少有应该是“私有”的方法被赋予“默认”(包级别)访问修饰符,以便可以对它们进行测试。(使用JUnit 4)
---原来这是一种错误的方法,因为这些方法“应该”是“私有的”。我不得不将它们更改为“私有”并修改测试用例。

2)为了增加代码覆盖率,我不得不调用公共方法并测试内部的“私有”方法。为此,我必须阅读/理解整个庞大的课程。 (这个类只有2个公共方法,大约15-20个私有方法,很少有方法调用深度为4-5'级别)。
---正如你可能已经想到的那样,事实证明这太复杂了。毫无疑问,很多这些私人方法都难以被测试 :(

最后,我厌倦了阅读所有这些旧代码并继续单独测试每个方法(使用'Reflection'来测试私有方法)。在一个古老而庞大的系统中,这很有意义。
我的每个单元测试都确保它只测试一种方法来确保其正确性。
如果任何方法无法按照预期的方式进行操作,则很容易以这种方式修复任何错误。 < / p>

当然,可以在这里提出论据,说应该尊重封装,我的测试用例应该只调用公共方法。
但是,当有一个私有方法是5级深层而没有做出预期的时候呢?你如何在旧的和遗留的代码中找到这个bug!你不希望每种方法都经过测试吗?
在这种情况下,该类没有机会改变其业务逻辑。因此,没有维持测试类的问题。
尽管这个课程是很多重构的理想选择,但是当你接近代码冻结时你不想接受它!:)

简而言之,答案可能因具体情况而异。根据您的需求/要求,您/您的团队将是最佳决策者,因为您最了解您的系统...... 希望;)