我知道您不应该测试私有方法,并且如果您看起来需要测试私有方法,那么那里可能会有一个类在等待发布。
但是,我不想拥有大量的类来测试它们的公共接口,我发现对于许多类来说,如果仅测试公共方法,最终我就不得不模拟很多依赖,而单元测试就是巨大且难以遵循。
我更喜欢在测试公共方法时嘲笑私有方法,而在测试私有方法时嘲笑外部依赖关系。
我疯了吗?
我知道您不应该测试私有方法,并且如果您看起来需要测试私有方法,那么那里可能会有一个类在等待发布。
但是,我不想拥有大量的类来测试它们的公共接口,我发现对于许多类来说,如果仅测试公共方法,最终我就不得不模拟很多依赖,而单元测试就是巨大且难以遵循。
我更喜欢在测试公共方法时嘲笑私有方法,而在测试私有方法时嘲笑外部依赖关系。
我疯了吗?
Answers:
您是部分正确的人-您不应该直接测试私有方法。类上的私有方法应该由一个或多个公共方法调用(也许是间接的-由公共方法调用的私有方法可以调用其他私有方法)。因此,在测试公共方法时,您还将测试私有方法。如果您有未测试的私有方法,则测试用例不足或私有方法未使用且可以删除。
如果您采用白盒测试方法,则在围绕公共方法构建单元测试时,应考虑私有方法的实现细节。如果您采用的是黑盒方法,则不应针对公共或私有方法中的任何实现细节进行测试,而应针对预期的行为进行测试。
就个人而言,我更喜欢在单元测试中使用白盒方法。我可以进行测试,以将要测试的方法和类置于不同的状态,这些状态会在我的公共和私有方法中引起有趣的行为,然后断言结果是我所期望的。
所以-不要嘲笑您的私有方法。使用它们来了解您需要测试的内容,以便更好地覆盖所提供的功能。在单元测试级别上尤其如此。
我认为这是一个非常糟糕的主意。
创建私有成员的单元测试的问题在于,它与产品生命周期的适应性很差。
您选择将这些方法设为私有的原因是,它们对于您的类试图做的事情并不重要-只是您当前如何实现该功能的帮助者。重构时,这些私有细节很可能会更改,并且在重构时会引起摩擦。
同样,公共成员和私有成员之间的主要区别是,您应该仔细考虑公共API,并对其进行良好的文档编制和检查(断言等)。但是,使用私有API时,仔细考虑是毫无意义的(浪费了精力,因为它的使用是如此本地化)。将私有方法放入单元测试中等于在这些方法上创建了外部依赖关系。意味着API需要稳定且有据可查(因为有人必须弄清楚为什么/何时使这些单元测试失败)。
我建议你:
感谢您倾向于测试此功能,并且很难通过当前的公共API对其进行测试。但是我个人比测试范围更重视模块化。
UnitTests测试 公共可观察到的行为,而不是代码,其中“ public”表示:返回值和与依赖项的通信。
“单位”是解决相同问题(或更确切地说:具有相同变更理由)的任何代码。那可能是单个方法或一堆类。
您不想测试的主要原因private methods
是:它们是实现细节,您可能希望在重构期间进行更改(通过应用OO原理来改进代码,而无需更改功能)。正是在这种情况下,您不希望更改单元测试,从而可以保证重构期间CuT 的行为不变。
但是,我不想拥有大量的类来测试它们的公共接口,我发现对于许多类来说,如果仅测试公共方法,最终我就不得不模拟很多依赖,而单元测试就是巨大且难以遵循。
我通常会遇到相反的情况:类越小(它们承担的责任越少),它们具有的依赖性越少,并且单元测试的编写和读取就越容易。
理想情况下,您将相同级别的抽象模式应用于类。这意味着您的类要么提供一些业务逻辑(最好是“纯函数”,仅对它们的参数起作用而不保持其自身的状态)(x),要么对其他对象调用方法,而不能同时对两者进行调用。
通过这种方式对业务行为进行单元测试是轻而易举的事,并且“委托”对象通常太简单而无法失败(无分支,无状态更改),因此无需进行单元测试,并且可以将其测试留给集成或模块测试进行。
当您是唯一从事代码工作的程序员时,单元测试会有所价值,尤其是在应用程序非常大或非常复杂的情况下。当您拥有大量使用同一代码库的程序员时,单元测试就变得至关重要。引入了单元测试的概念来解决在这些较大的团队中工作的一些困难。
单元测试帮助大型团队的原因全在于合同。如果我的代码正在调用其他人编写的代码,那么我就假设其他人的代码在各种情况下将要做什么。如果这些假设仍然成立,我的代码仍然可以使用,但是我如何知道哪些假设有效,以及如何知道这些假设何时更改?
这就是单元测试的用处。类的作者创建单元测试以记录其类的预期行为。单元测试定义了使用类的所有有效方式,并且运行单元测试可以验证这些用例是否按预期工作。另一个想要利用您的类的程序员可以阅读您的单元测试,以了解他们对类的期望行为,并将其用作他们对类工作方式的假设的基础。
这样,类和单元测试的公共方法签名共同构成了类作者和其他在其代码中使用该类的程序员之间的契约。
在这种情况下,如果包括私有方法的测试会怎样?显然,这没有任何意义。
如果您是唯一处理代码的程序员,并且希望将单元测试用作调试代码的方式,那么我认为这没有什么害处,它只是一个工具,您可以将其用于任何可用于您,但这不是引入单元测试的原因,并且不能提供单元测试的主要好处。
在回答这样的问题之前,您需要确定您实际想要达到的目标。
您编写代码。您希望它履行合同(换句话说,它可以完成应做的事情。写下它应做的事情对某些人来说是巨大的进步)。
要合理地确信代码可以完成预期的工作,您可以盯着它足够长时间,或者编写测试代码以测试足够的情况,以说服您“如果代码通过所有这些测试,那么它是正确的”。
通常,您只对某些代码的公共定义接口感兴趣。如果我使用您的库,则不在乎您是如何使其正常工作的,仅是它能够正常工作。我通过执行单元测试来验证您的库是否正确。
但是您正在创建库。使它正常工作可能很难实现。假设我只关心该库是否正确执行X,所以我对X进行了单元测试。您,负责创建该库的开发人员,通过将步骤A,B和C组合在一起来实现X,这两个步骤都不是很简单的。为了使您的库正常工作,您需要添加测试以验证A,B和C均正常工作。您需要这些测试。说“您不应该对私有方法进行单元测试”是毫无意义的。您需要测试这些私有方法。也许有人告诉您单元测试私有方法是错误的。但这仅意味着您可能不将它们称为“单元测试”,而将其称为“私有测试”或您喜欢称呼它们的任何东西。
Swift语言解决了您不想将A,B,C公开为公共方法的问题,因为您想通过给函数赋予属性“可测试”来对其进行测试。编译器允许从单元测试而不是非测试代码中调用私有可测试方法。