Let's assume we are designing a Stack class test-first (TDD):
public class Stack<T> {
private T[] elements = new T[16];
private int size = 0;
...
}
This Stack makes use of a size 16 internal array to store its elements. It will work fine until you need to add a 17th element. As I might need a 17th element, I decided to add that functionality to my Stack, so I started thinking about what name I could give to the test that'd make have to add that functionality. That will be the subject of my first question.
I first chose something of the form of:
Should_Be_Able_To_Correctly_Increase_Its_Inner_Array_Size()
and then
Should_Handle_More_Items_Than_The_Default_Internal_Array_Size()
but after thinking for a bit I came to the conclusion that maybe something like the following would be more apropriate:
Should_Double_Its_Size_Every_Time_Its_Full()
My reasoning would have to do that in the first case, I am saying only what it does, but not when. In the second, I am saying when to add more items, but I am also stating how I'm thinking of achieving it (internally), which may not be correct. In my view (I'm not sure I am correct), my tests should the possible interactions of my SUT with the exterior, and not on how it is implemented internally. Am I right?
It looks to me that the 3rd options is the best, as it clearly states what it does(grow in size -- in fact, double its size), when it does(when it's full) and doesn't ties me to any specific implementation (I could maybe later want to change it to an internal ArrayList!).
Which leads me to my second question: Assuming I did all the Unit-Tests for my Stack class that uses internally an Array and it works fine and as expected, should my tests remain intact if I later want to refactor and change the Array to an ArrayList or any other kind of data-structure? Or should the tests in any way reflect that? I'd guess no, but I'm not sure.