我有两个函数,foo
和bar
。
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创建的 - 例如首先编写测试,然后实现函数以使测试通过。测试清单:
foo()
被定义foo()
做得很好foo()
会抛出TypeError
bar()
被定义bar()
做得很好bar()
会抛出TypeError
如您所见,这些函数都具有重复功能 - 它们正在测试每个参数的正确性。由于这个检查在我的函数中非常常见,并且可能会更复杂(检查参数计数是否在某个范围内,检查参数类型等),我决定将其移到单独的装饰器函数check
中。
所以我为check
编写了测试并实现了check
本身。
现在重构步骤 - 我已经利用了check
,所以函数现在看起来如下:
foo = check(1, function() {
do work;
});
bar = check(3, function() {
do work;
});
我现在应该做些什么来检查foo()
和bar()
检查正确数量的参数?我可以放下它们吗?
当我实现函数buzz()
时,它立即使用check()
(因为它现在被用作定义函数的方式),我是否必须为它编写测试以获取正确数量的参数?我犹豫了,因为这个测试总是绿色的,因为所有的工作都是在装饰器里完成的,所以有没有需要测试?
我会避免保留多个检查相同代码的单元测试,因为将来:
check
函数,则必须更改2个测试而不是1个。check
,你会得到两个失败:一个指的是foo
,另一个指的是bar
,而且很明显被破坏的是check
函数。所以,我只保留一组测试,明确命名为check
函数的测试,甚至更好,不要使用你的程序函数来测试它们(不是foo
在你的例子中都没有bar
)但是使用假的函数仅用于测试目的。
通过这种方式,您可以在将来更改foo
或bar
以使用,例如check2函数,而无需检查函数的中断测试
据我所知,这是最好的理论方法,但要务实:如果你不希望在你的代码的很大一部分中使用check
函数,不要试图遵循这种方式:你的目标必须有主程序运行顺畅,没有一套漂亮的测试......
经典的TDD概念需要一些额外的修改才能将它们应用到动态语言,如Javascript(由于缺少类,特定的闭包使用......)这就是我们拥有像Jasminejs这样的测试库的方式。我不能明确告诉你如何处理你的功能,但我知道一切都不需要测试。有些事情真的很明显,他们只需要一些理智检查。经验法则是测试可能破坏的东西。例如验证,数据库访问,用户输入......
我认为你是在正确的道路上,TDD使代码重复更加明显(检查参数代码必须在有或没有TDD的情况下删除它的重复)并且你听你的测试并分开检查的责任,现在你有两个责任:
在单元测试级别,这是完美的,我认为,或许在其他方面,您需要一些集成或系统测试来检查您是否正确地使用他的检查器编写功能。
如果有单独的声明,则需要进行测试。所以在你的情况下,你需要保持测试要求foo()
和bar()
都使用check
函数。这些测试可能比您编写的原始测试更简单:例如,他们可能只检查是否抛出了错误,而没有查看错误消息。
如果检查功能现在被打破,例如什么都不做,那么会有多个检测器检测到这一点。这不是问题,因为你会将check
函数的测试置于顶部,因此第一次失败将直接指向根本原因。