冗余测试是否可以在TDD方法中废弃并删除?

时间:2014-02-01 17:40:34

标签: javascript unit-testing testing tdd methodology

我有两个功能,foobar

function foo() {
    if (arguments.length !== 1) {
        throw new TypeError('only one argument expected');
    }

    do work;
}

function bar() {
    if (arguments.length !== 3) {
        throw new TypeError('exactly three arguments expected');
    }

    do work;
}

这些功能是根据TDD创建的 - 例如首先编写测试,然后实现函数以使测试通过。测试清单:

  1. foo()已定义
  2. foo()正常工作
  3. 当给出错误的参数数量时,
  4. foo()会抛出TypeError
  5. bar()已定义
  6. bar()正常工作
  7. 当给出错误的参数数量时,
  8. bar()会抛出TypeError
  9. 如您所见,这些函数都具有重复功能 - 它们正在测试每个参数的正确性。由于这个检查在我的函数中非常常见,并且可能会更复杂(检查参数计数是否在某个范围内,检查参数类型等),我已经决定将它移到单独的装饰器函数{{1 }}

    所以我为check编写了测试并实现了check

    现在重构步骤 - 我利用了check,所以函数现在看起来如下:

    check

    我现在应该做什么来检查foo = check(1, function() { do work; }); bar = check(3, function() { do work; }); foo()检查正确数量的参数?我可以放下它们吗?

    当我实现函数bar()时,它立即使用buzz()(因为它现在被用作定义函数的方式),我是否必须为它编写测试以获取正确数量的参数?我犹豫了,因为这个测试总是绿色的,因为所有的工作都是在装饰器里完成的,所以有没有需要测试?

4 个答案:

答案 0 :(得分:1)

我会避免让多个单元测试检查相同的代码,因为将来会:

  1. 如果您故意以破坏测试的方式更改check功能,则必须更改2个测试而不是1个。
  2. 如果您无意中破坏了check,您将会遇到两次失败:一次是foo,另一次是bar,而且可能并不明显check功能。
  3. 所以,我只保留一组测试,明确命名为check函数的测试,更好的是,不要使用程序函数来测试它们(不是foo在你的例子中bar但是使用仅用于测试目的的假函数。

    通过这种方式,您可以在以后更改foobar以使用,例如check2函数,而无需检查函数的中断测试

    根据我的说法,这是最好的理论方法,但要务实:如果你不希望在你的很大一部分中使用check函数,请不要尝试这样做代码:你的目标必须让主程序顺利运行,而不是一组漂亮的测试......

答案 1 :(得分:1)

经典TDD概念需要一些额外的修改才能将它们应用于动态语言,如Javascript(由于缺少类,特定的闭包使用......)这就是我们拥有像Jasminejs这样的测试库的方式。 我不能明确告诉你如何处理你的功能,但我知道一切都不需要测试。有些事情真的很明显,他们只需要一些理智检查。经验法则是测试可能破坏的东西。例如验证,数据库访问,用户输入......

答案 2 :(得分:1)

我认为你是在正确的道路上,TDD使代码重复变得更加明显(检查参数代码必须在有或没有TDD的情况下删除它的重复)并且你听取你的测试并分开检查的责任,现在你有两个责任:

  • 使用自己的一组测试来检查参数。
  • 函数的工作,有自己的设置测试,总是正确输入。

在单元测试级别,这是完美的,我认为,或许在其他方面,您需要进行一些集成或系统测试,以检查您是否正确地使用他的检查器编写功能。

答案 3 :(得分:0)

如果有单独的声明,则需要进行测试。因此,在您的情况下,您需要保留要求foo()bar()都使用check函数的测试。这些测试可能比您编写的原始测试更简单:例如,他们可能只检查是否抛出了错误,而没有查看错误消息。

如果检查功能现在被打破,例如什么也不做,那么会有多个检测器检测到这一点。这不是问题,因为您会将check函数的测试置于顶部,因此第一次失败将直接指向根本原因。