首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么单元测试私有方法被认为是不好的做法?

为什么单元测试私有方法被认为是不好的做法?
EN

Software Engineering用户
提问于 2018-10-19 15:20:45
回答 6查看 40.7K关注 0票数 36

上下文:

我目前正在用Python做一个小项目。我通常用一些公有的方法来构造我的类,这些方法是文档化的,但主要是处理高级概念(类的用户应该知道和使用什么),以及一组负责复杂或低级处理的隐藏方法(从下划线开始)。

我知道,测试对于增强对代码的信心以及确保以后的任何修改都不会破坏以前的行为是必不可少的。

问题:

为了在可信的基础上构建更高级别的公共方法,我通常对私有方法进行测试。我发现更容易找到代码修改是否引入了回归以及在哪里。这意味着这些内部测试可以中断一些小的修改,并且需要修复/替换。

但我也知道,单元测试私有方法至少是一个有争议的概念,或者更经常被认为是不好的做法。原因是:只有公众行为才能被测试(参考)

问题:

我确实关心以下最佳做法,并想了解:

  • 为什么在私有/隐藏方法上使用单元测试是不好的(风险是什么)?
  • 当公共方法可以使用低级别和/或复杂处理时,最佳实践是什么?

精确性:

  • 这不是如何提问的问题。Python没有真正的隐私概念,隐藏的方法根本没有列出,但是当您知道它们的名称时,就可以使用它了。
  • 我从来没有被教过编程规则和模式:我的最后一节课是从80‘S.我主要通过试用和失败学习语言,并在互联网上提供参考(多年来,我最喜欢的是堆栈交换)
EN

回答 6

Software Engineering用户

回答已采纳

发布于 2018-10-19 20:43:39

有几个原因:

  1. 通常,当您尝试测试一个类的私有方法时,它是一种设计气味(冰山类,没有足够的可重用公共组件,等等)。几乎总是有一些“更大”的问题在发挥作用。
  2. 您可以通过公共接口对它们进行测试(这就是您想要测试它们的方式,因为客户端就是这样调用/使用它们的)。您可以通过对您的私有方法的所有通过测试看到绿灯,从而获得一种虚假的安全感。通过公共接口在私有函数上测试边缘用例更好/更安全。
  3. 通过测试私有方法,您将面临严重的测试重复(看起来/感觉非常相似的测试)的风险。当需求发生变化时,这会产生重大后果,因为会有更多的测试中断。它还可以使您处于一个很难重构的位置,因为您的测试suite...which是最大的讽刺,因为测试套件是为了帮助您安全地重新设计和重构!

如果您仍然想测试私有部分(如果它困扰您和YMMV,请不要使用它,但它在过去对我很有用):有时编写私有函数的单元测试只是为了确保它们的工作方式与您认为它们可能是有价值的(特别是如果您对一种语言还不熟悉的话)。但是,在您确定它们有效之后,请删除测试,并始终确保面向公共的测试是可靠的,并且如果有人对所述的私有函数进行了惊人的更改,就会发现它们是可靠的。

什么时候测试私人方法:由于这个答案已经(有点)流行了,我有义务提到“最佳实践”就是“最佳实践”。这并不意味着你应该以教条或盲目的方式去做。如果您认为您应该测试您的私有方法,并且有一个合理的理由(比如您正在为一个遗留应用程序编写特性测试),那么测试您的私有方法。具体情况总是胜过任何一般规则或最佳做法。只是要注意一些可能出错的事情(见上文)。

我有一个详细的答案,在这里我不再重复:https://stackoverflow.com/questions/105007/should-i-test-private-methods-or-only-public-ones/47401015#47401015

票数 39
EN

Software Engineering用户

发布于 2018-10-19 15:52:27

考虑到单元测试的主要目的之一是,您可以重构程序的内部,然后能够验证您没有破坏它的功能,如果单元测试的粒度非常细,以致于程序代码的任何更改都要求您重写测试,则会适得其反。

票数 24
EN

Software Engineering用户

发布于 2018-10-19 15:54:33

为私有方法编写单元测试将单元测试与实现细节联系起来。

单元测试应该在类的外部表面(它是公共API)测试类的行为。单元测试不应该知道任何关于类内部的信息。当涉及重构时,编写针对类的实现细节的单元测试将束缚您的双手。重构几乎肯定会破坏这些测试,因为它们不是稳定API的一部分。

也就是说,为什么要为您的私有方法编写单元测试?

在单元测试和增量开发之间有一种自然的紧张关系。使用REPL (读-古-打印循环)的软件开发人员可以证明,随着类或函数的“增长”,快速编写和测试小部分功能是多么的有效率。在由单元测试驱动的环境中,唯一能做到这一点的方法是为私有方法编写单元测试,但是这样做有很多摩擦。编写单元测试需要时间,您需要一个实际的方法来对其进行测试,并且您的测试框架需要支持将该方法保持为私有的能力,这样它就不会污染您的外部API。

像C#和.NET这样的生态系统可以创建类似REPL的环境(比如Linqpad这样的工具),但是它们的效用是有限的,因为您无法访问您的项目。Visual中的即时窗口不方便;它仍然没有完整的Intellisense,您必须在其中使用完全限定的名称,并且每次使用它时它都会触发一个构建。

票数 15
EN
页面原文内容由Software Engineering提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://softwareengineering.stackexchange.com/questions/380287

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档