From what I have learned about TDD and unit testing is that I should test the behavior of public method of an class. Private method will get tested by public method method that called them anyway.
Fair enough, this seem really good and simple.
Here is where it's starting to get odd. I code in javascript where the concept of visibility doesn't exists...
Ok then, nevermind, I just have to pretend there is one on method of my class.
So, I kept going and now I found myself asserting too many elements and re-testing the same thing more then once. So, I'm kind of having the third biggest mistake listed in this top 5 TDD mistakes article.
But damn it, I really stood with testing only public method and the behavior expected by the customer like Sergey Berezovskiy explain here.
I could solve my problem VERY EASILY by testing a "private" method. Since I'm in javascript, the private method is accessible anyway as mentioned earlier. This indicate me, that something smell in my code. I know what I would do in c# to remove this smell, but I don't in JS.
Example:
MyClass = function ()
{
var self = this;
self.Tasks = [];
self.IsExpanded = false;
self.IsLoaded = false;
self.LoadTasks = function ()//Private
{
//api call to load task
self.SortTasks();
};
self.SortTasks = function (tasks)//Private
{
//Sort self.Tasks array
};
self.Method3 = function ()//Public
{
//Do stuff
if (HasDoneSomething)
{
self.SortTasks();
}
};
self.Method2 = function (param)//Public
{
//Do stuff
self.UpdateSort();
}
self.Method1 = function ()//Public
{
if (self.IsExpanded)
self.Collapse();
else
self.Expand();
};
self.Expand = function ()//Private
{
if (!self.IsLoaded)
{
self.LoadTasks();
}
self.IsExpanded = true;
};
self.Collapse = function ()//Private
{
self.IsExpanded = false;
};
}
All three methods have an impact on the sort of Tasks. This result into an assertion on the sort order that repeat itself in multiple test.
test("Some test 2", 2, function ()
{
//Setup
var myClass = Builder.Build();
//Action
myClass.Method2(SomeParam);
//Assertion
ok( jobWasDoneProperly, "Task should now be started");
ok( sortOk, "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( sortOk, "Task started was moved after already started tasks and before unstarted ones");
});
Having assertion on the sort also lead to the mistake #2 in the article stated above because it required some setup to verify the sort.
So if I bypass the private rule, I can test the method "SortTasks" alone. Then in other tests, I would only assert that method "SortTasks" is called with stub/spy instead of actually testing the resulted sort each time.
What is the proper way to address this issue? Where did I go wrong?
In c#, I could simply create a new class that inherit of List. Add a public sort method to this class. Then use this class to hold "Tasks" in "MyClass". Test the sort method and bingo! But I'm in javascript, my array is actually an Knockout obserbaleArrays, and I'm new with javascript... :|
Aucun commentaire:
Enregistrer un commentaire