如何避免在javascript中使用单元测试重新测试相同的行为? (方法可见性和单元测试)

时间:2015-06-03 21:55:15

标签: javascript unit-testing tdd

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"用间谍调用,而不是实际测试"方法1","方法2"和方法3"。这并没有减少断言次数,但由于需要的验证较少,因此确实减少了设置的长度。但是,这表明代码中有异味,因为它会违反TDD原则。

在c#中,单向将创建一个新的类名" TaskList"继承List。实现一个公共排序方法。然后使用这个类来保存"任务"在" MyClass"而不是数组。通过这种方式,我们不会违反规则并且不会测试私人方法"一切都会很好。但是我在javascript中,我的数组实际上是一个Knockout obserbaleArrays,我简单地检查过是否有可能在javascript中继承一个数组。这似乎有可能,但我没有兴趣去那里,因为它似乎没有内置,太复杂。我不想保持这样的事情。

在尊重“不要测试私人方法”的情况下,在这个问题上测试排序的正确方法是什么?规则?

1 个答案:

答案 0 :(得分:-1)

首先在TDD中,测试数量与您的代码量相比还不够。 对于这段代码,您可能会获得200多行测试。

你说的正确,在C#中你会从列表中继承,而你可能会通过构造函数注入它。你可以轻松地与间谍一起做。

你应该测试整个SUT的结果,所以如果你的sut正在做某事,并且为了实现它而对它进行排序,你就不应该测试排序 - 或者通过间谍来看看会发生什么。

您也可以轻松实现“私人”功能

MyClass = function(){
 _function privateFunc(){}
}

现在你无法从外面访问它

此外,如果您是JS新手,我建议您尝试使用jasmine进行测试,这对C#开发人员非常有用