unit testing辅助方法?

我有以前有大量方法的类,所以我将这个方法的工作细分为’helper’方法。

这些辅助方法被声明为private以强制封装 – 但是我想对大型公共方法进行unit testing。 对辅助方法进行unit testing也是好的,就好像其中一个方法失败了,调用它的公共方法也会失败,这样我们就可以找出它失败的原因了吗?

另外,为了使用模拟对象测试这些,我需要将其可见性从私有更改为受保护,这是否可取?

一种方法是省略private并将测试放在同一个包中。 然后测试可以调用内部方法,但没有其他人(=在包外)。

此外,失败的内部方法应该产生错误消息,以便于解决问题。 当您将代码投入生产时,您将看到比测试更少的内容,并且您将面临很大的压力来快速解决问题。 因此,一小时后在这里花一分钟就可以让你的老板坐在你的脖子上。

这闻起来就像你有错误的问题。 你所描述的类似于创建一个子unit testing,这让我相信你的unit testing毕竟是在测试一个单元。

这不是对你要做的事情的批评:从“我们今天所处的位置”到“其他可以更好的地方”是一个成功的举措。 但是,建议您退后一步来评估您的位置 – 了解您当前情况与某些柏拉图式理想之间的差异有助于展示新的可能性。

这里有很多关于确定你的助手方法的建议。 另一种可能性是检查实现以确定当前实现中是否存在潜伏类。 创建一个新的类和一套测试来运用它总是可以接受的。

请注意,这种方法可以使您免于重构:您可以在不更改测试套件的情况下更改实现(因为即使辅助对象不再是生产实现的一部分,辅助对象的unit testing也会继续通过),并且您得到了实现的干净包装及其测试(用例:你认为bozo-sort是错误的实现,不应再使用。如果bozo-sort实现是隔离的,那么你只需删除它及其测试。但是当bozo-sort实现的测试与所有其他测试纠缠在一起时,会涉及更多的思考)。

它还可以帮助您查看为什么对代码进行unit testing。 如果其中一个原因是“使重构安全”,那么您不希望编写将您锁定到实现中的测试。

如果你的课真的那么大,那么听起来你应该打破辅助对象 ,而不仅仅是辅助方法 (尽管提取方法通常是一步之遥)。 完成后,您的旧类变得更简单,更容易测试(可能使用模拟,也许不是),您可以直接在新的支持类上测试方法。

我的偏好是通过对象的公共API进行测试。 如果那太难了,那么就暗示该对象应该被打破。

如果您想测试Helper方法,可以将它们从私有方式更改,但您可能会考虑这一点。

您不应该对您的实现的私有细节进行unit testing,主要是因为它可能会因重构和“中断”您的测试而发生变化。

我对这里的一些答案感到非常震惊。

实质上有些人说“不要测试私有代码,因为这违反了TDD范式”

测试该死的代码。 做任何你需要的东西,以确保它完全按照它应该的方式工作。

就个人而言,我会使方法受到保护或默认,编写测试,运行测试,并在成功时,恢复为私有。 此时,我会注释掉相关的测试,并在它们上面留下一个指令块:

/ **对此我很抱歉,但是我inheritance了一个混乱… *如果您需要测试这些方法,请在源代码中公开它们并取消注释以下*行* /

但绝对不要让严格遵守开发方法妨碍改进代码。

这是其中一个我会说继续违反规则的案例。

如果你是从头开始设计这个类,你绝对不希望帮助方法自己进行unit testing,但是……因为你正在重构现有的类,所以可以弯曲规则以确保你不要什么都不打破。

让它们受到保护会让你自己测试帮助器,以确保它们仍然具有你期望的行为,因为你从大毛球方法中拉出逻辑,并允许你将它们存根并返回固定的响应,以便你可以确保您重构的大方法对于辅助方法的某些结果的行为与预期一致。

但那时你还没有完成。 拆分方法并不是真正解决问题的根源。 既然你已经分解了这个方法,并且有一组(稍微非正统的)测试可以准确地显示所有逻辑的function,那么你就可以重新检查整个类并试图找出方法的原因。一开始这么大。 最有可能的是,您的整个class级也需要分解成具有离散职责的较小单元,这样在不弯曲任何规则的情况下更容易测试。

你基本上有两个选择:

  1. 将辅助方法的范围从private增加到default。 然后,您可以测试这些方法(假设测试类与测试主题位于同一个包中)。 这提高了类的可测试性,但是您牺牲了一些封装

  2. 保持一切顺利。 这将阻止您编写非常细粒度的测试,但不要求您牺牲任何封装。

就个人而言,我会选择(2),因为你不应该真的需要测试私有方法。 该类应该通过它的公共接口进行测试(它反过来将调用私有方法。测试私有方法可能导致脆弱的测试,即只有类的内部行为发生变化时才会失败的测试。

还有第三种选择(我不愿意提及):使用reflection(或其他一些伏都教)来调用测试类中的私有方法。 这具有(1)的缺点以及reflection代码固有的缺点(例如绕过类型检查并且难以阅读)

正如Don和Dror所说,将方法设为公共,这样你就可以为它们创建unit testing,从而打破封装。 然后,您将自己绑定到特定实现。 通过将它们公开,您向全世界声明这些方法是已发布接口的一部分,因此它们的规范被锁定。

就个人而言,我会寻求更实用的解决方案:将它们保密,不要编写unit testing。 如果你遇到一个公共方法失败的情况你无法找出原因,但你认为它可能是你的一个私有方法中的问题,那么暂时将它们公开,编写unit testing,调试,当你’完成后,再次将它们设为私有并注释掉unit testing。

您可以通过编写执行代码部分的unit testing来对这些辅助方法进行unit testing。

你在这个类中定义了一个公共API是有原因的,对吧? 测试一下。 如果它有效,该课程就可以了。

使用代码覆盖率工具来帮助您了解是否正在测试该类的足够部分,如果不是,请编写更多unit testing来使用公共API并触及那些未被覆盖的角落。

Interesting Posts