【发布时间】:2015-06-03 21:55:14
【问题描述】:
TDD原理:
- 测试类的公共方法的行为。私有方法无论如何都要经过测试,因为公共方法调用了它们。不要测试私有方法。
- 测试客户的预期行为,如 Sergey Berezovskiy 解释 here.
公平地说,这看起来非常好和简单。然而,在下面的例子中,这个原理导致对同一事物进行多次重新测试。这导致了top 5 TDD mistakes article. 中列出的第二和第三大错误,即“设置过多”和“断言过多”。
例子:
MyClass = function ()
{
var self = this;
self.Tasks = [];
self.IsExpanded = false;
var _IsLoaded = false;
//Private
function _LoadTasks()
{
//api call to load task
_SortTasks();
};
//Private
function _SortTasks(tasks)
{
//Sort self.Tasks array
};
//Public
self.Method3 = function ()
{
//Do stuff
if (HasDoneSomething)
{
_SortTasks();
}
};
//Public
self.Method2 = function (param)
{
//Do stuff
_SortTasks();
}
//Public
self.Method1 = function ()
{
if (self.IsExpanded)
_Collapse();
else
_Expand();
};
//Private
function _Expand()
{
if (!_IsLoaded)
{
_LoadTasks();
}
self.IsExpanded = true;
};
//Private
function _Collapse()
{
self.IsExpanded = false;
};
}
在上面的示例中,三个公共方法可能会影响任务的顺序。这导致对排序顺序的断言在多个测试中重复。
test("Some test 2", 2, function ()
{
//Setup
var myClass = Builder.Build();
//Action
myClass.Method2(SomeParam);
//Assertion
ok( jobWasDoneProperly, "Task should now be started");
ok( resuledSortIsGood, "Task started was moved after already started tasks and before unstarted ones");
});
test("Some test 3", 3, function ()
{
//Setup
var myClass = Builder.Build();
//Action
myClass.Method3();
//Assertion
ok( taskLoadedCorrectly, "Tasks are loaded");
ok( taskAreExpanded, "Tasks are expanded");
ok( resuledSortIsGood, "Task started was moved after already started tasks and before unstarted ones");
});
对排序进行断言需要一些设置来验证结果排序。从而导致如前所述必须进行大量设置的错误。
问题可以通过测试“私有”方法“SortTasks”轻松解决。这样,我只能断言“SortTask”是用间谍调用的,而不是在“method1”、“method2”和“method3”的测试中实际测试结果排序。这不会减少断言计数,但确实减少了很多设置的长度,因为需要较少的验证。但是,这表明代码中有异味,因为它违反了 TDD 原则。
在 c# 中,一种解决方法 是创建一个继承 List 的新类名“TaskList”。对其实施公共排序方法。然后使用这个类来保存“MyClass”中的“Tasks”而不是一个数组。这样,我们就不会违反“不测试私有方法”的规则,一切都会很好。但我在 javascript 中,我的数组实际上是一个 Knockout obserbaleArrays, 我简要检查了是否可以在 javascript 中继承数组。这似乎是可能的,但我对去那里不感兴趣,因为它似乎根本没有内置并且太复杂了。我不想维持这样的事情。
在尊重“不测试私有方法”规则的同时测试这个问题的排序的正确方法是什么?
【问题讨论】:
标签: javascript unit-testing tdd