【问题标题】:TDD duplicate assertionsTDD 重复断言
【发布时间】:2012-08-31 16:02:00
【问题描述】:

大家的共识似乎是在做 TDD 时不要测试私有方法。

Should Private/Protected methods be under unit test?

我不断遇到同样的情况。我有一个私有方法(例如,它将所有选项都关闭)。它改变了很多状态,并被一些公共方法调用。无论调用哪个公共方法(所有选项都设置为关闭),私有方法对状态所做的更改都将保持不变。

在不添加许多有效地做同样事情的测试的情况下,测试这个私有方法的功能的最佳方法是什么?

顺便说一句,我正在使用 QUnit 来测试 Javascript 对象。

这是我的课程的一个过于简化的版本。

http://jsfiddle.net/twistedinferno/UMgAx/

编辑

我在这里真正想问的不是“我应该还是不应该测试私有方法”,因为这已经得到了回答,而答案是否定的。我想知道如何最好地测试每个公共方法,记住由于使用了我的私有方法,许多断言将是相同的。许多公共方法调用相同的私有方法。是否可以有很多重复的断言来测试当许多公共方法中的每一个调用我的私有方法时发生的状态变化?

新的测试方法 http://jsfiddle.net/twistedinferno/JHzWh/

【问题讨论】:

    标签: unit-testing tdd qunit


    【解决方案1】:

    测试公共方法。

    或者,更一般地说,测试对象的外部可见界面。

    如果私有方法被公共方法使用,它的使用将被测试作为结果。但是私有方法本身是私有的,对于该对象之外的任何东西都不是问题,包括测试。

    这些测试不应该知道或关心这样的私有方法是否存在,更不用说他们是否正在测试它。他们应该测试所有公共功能。

    如果许多测试都在做同样的事情,这是否表明公共功能中存在不必要的重叠?也许那里有重构的空间?当然,这完全是猜测,没有看到任何代码。可以举个例子吗?

    编辑

    额外的断言重复了相同的击键,但测试明显不同,因为它们测试的是不同的面向外部的功能。您始终可以将重复的断言重构为每个测试调用的单个函数。一种自定义聚合断言。只要公共方法继续具有相同的可观察(和可测试)行为,那就没问题了。一旦改变,它的测试当然也需要改变。

    【讨论】:

    • 这里是一个过于简化的小提琴jsfiddle.net/twistedinferno/UMgAx 我的真实示例被证明太大而无法添加或太复杂而无法浓缩。公共功能肯定有重叠,但我不确定该怎么做。
    • @TwistedInferno:在那个例子中,看起来您打算测试的是后三个函数,而第一个函数是私有函数? (诚​​然,我并不精通 JavaScript 对象。)对于外部观察者来说,私有函数是否存在并不重要。三个公共的都经过测试。他们都在内部使用相同的私有函数这一事实对测试无关紧要。 (实际上,测试也可以有一个共享的私有函数来验证普遍预期的结果。)
    • 是的,带下划线的方法是私有的,没有下划线的方法是公共的(只是一种约定,另一种选择是在内存方面效率较低的闭包)。所有的灯都是公开的。好的,那么我应该为每个公共方法的每个光值包含四个断言吗? (即 4 x 3 断言)对我来说这是重复测试,感觉不太对。
    • @TwistedInferno:它重复了相同的击键,但测试明显不同,因为它们正在测试不同的向外功能。您始终可以将重复的断言重构为每个测试调用的单个函数。一种自定义聚合断言。只要公共方法继续具有相同的可观察(和可测试)行为,那就没问题了。一旦一个变化,它的测试当然也需要变化。
    【解决方案2】:

    我同意 bcariso 和 David 的观点。你不应该测试,也不应该测试私有方法。

    需要注意的一点是,如果您的私有方法如此庞大和重要,以至于您觉得必须对其进行测试,您应该考虑将其提取为它自己的辅助类的公共方法。

    在 Javascript 中,原则相同,只是您将其设为公开可见的函数或模块(如果您使用该模式)。

    【讨论】:

    • 感谢 Assaf,并不是我的私有方法太大,只是它在重复行为,因此我需要重复测试。
    • 在这种情况下,我认为这是一个明确的信号,表明您应该将其设为完全公开的功能,因为它可以重复使用。
    • 谢谢阿萨夫。它只会重复课堂内部的行为,所以我不确定将其公开是否是一个好主意;私有方法不需要公开。也许您可以详细说明...
    • 这个想法是这样的——如果你两次做同样的事情,你应该考虑创建一个可以在多个业务功能中使用的实用函数。我建议公开它只是因为 JavaScript 不支持“内部”封装的概念(就像在 C# 中一样)。例如,如果您只需要在一个函数中访问 Web 服务(例如获取天气),您可以在该函数中编写服务访问代码。但是,如果您发现在其他地方需要它,则需要将其重写为可以在任何地方使用的实用函数。使其成为您的基础架构的一部分。
    【解决方案3】:

    鉴于您正在练习 TDD,我假设如果没有需要编写的测试,相关私有方法中的每一行代码都不会存在。这意味着不需要独立于公共接口测试私有函数。

    谢谢!

    布兰登

    【讨论】:

    • 非常感谢您的意见,但我不确定我是否遵循。即使没有专门针对它进行测试的测试,私有方法也会存在。拥有私有方法的原因是为了封装类似的行为并删除重复的代码。我同意,我不需要独立测试私有方法,但我的问题是我在每个公共方法的每个测试中都有许多完全相同的断言,并且感觉不太正确,因为我多次重复断言。
    猜你喜欢
    • 1970-01-01
    • 2020-06-20
    • 2023-03-15
    • 2015-01-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-20
    相关资源
    最近更新 更多