1

I'm new to TDD. I've created all the main functions (insert, search, remove etc.). This is my insert_beginning() function:

def insert_beginning(self, node):
    '''
    Inserts a Node to the beginning of the list.
    '''
    node.set_next(self.head)
    self.head = node

My question is, how do I properly unit-test this function? The only way I can thing of is:

class ListFunctionsTest(unittest.TestCase):

    def setUp(self): 
        self.list1 = LinkedList()
        self.node1 = Node(1)

    def test_insert_beginning(self):
        self.list1.insert_beginning(self.node1)
        self.assertEqual(self.list1.__str__(), "1")

but then the test_insert_beginning() function is dependent on my

__str__() # string representation of my linked list

function. I have a feeling that the way I'm testing it is not correct (because the moment I decide to change the way my linked list is represented, then I'd end up having to rewrite my test cases). Is there a way to test my insert_beginning() function without depending on another function which I created / customized?

Edit: For those wondering, currently, the string representation of my linked list is just a string representation of my nodes separated by commas. For example, a linked list with the nodes 1, 2 and "a" would be represented like this:

1, 2, "a"

However, I am planning on changing my linked list's string representation (planning on changing the __ str __() function). This is when I realized that the way I am unit testing might be incorrect.

Edit 2 (a comment suggested that I create a function which helps me find the index of an item in the linked list): Assume that a function called index_of(self, item) exists, and this function finds the index of an item. Assume that this is the unit test for the index_of(self, item), and assume that the test cases successfully pass.

def test_index_of(self):
    myList = LinkedList()
    node1 = Node(1)
    node2 = Node(2)
    node3 = Node(3)
    myList.head = node1
    node1.next = node2
    node2.next = node3

    self.assertEqual(self.myList.index_of(1), 0)
    self.assertEqual(self.myList.index_of(2), 1)
    self.assertEqual(self.myList.index_of(3), 2)

Now, is it okay for me to rely on the index_of(self, item) function to determine if insert_beginning(self, node) is working correctly? In other words, is it okay if my test_insert_beginning() function is:

class ListFunctionsTest(unittest.TestCase):

    def setUp(self): 
        self.list1 = LinkedList()
        self.node1 = Node(1)

    def test_insert_beginning(self):
        self.list1.insert_beginning(self.node1)
        self.assertEqual(self.list1.index_of(1), 0)
8
  • 1
    Do you not have some way to get the data from your linked list? Why not check that? i.e. get the value at the first node and check that it equals 1. Then check the next one and make sure you get an error. Commented Jun 13, 2015 at 6:36
  • I imagine what would happen if the lines of code didn't exist, or did something different. How can you detect that? Commented Jun 13, 2015 at 6:40
  • 1
    Yup. The only thing you can control is the data you add, so that's the only thing you can reliably check. Commented Jun 13, 2015 at 6:46
  • 1
    Something I notice is that your methods seem to expose the Nodes rather than working with the values themselves. A well encapsulated linked list will not make the caller think about nodes. Callers don't care about the nodes; they care about the values. Nodes are an implementation detail. Commented Jun 13, 2015 at 16:17
  • 1
    Your method is def insert_beginning(self, node):, which clearly takes a node as an argument. Creating the Node object is something the calling code should not have to do; it's an implementation detail of the list. The method should be def insert_beginning(self, element):, and wrapping the element in a node would be internal to the method. Commented Jun 14, 2015 at 3:36

1 Answer 1

3

You have a good point. You don't want to tie yourself to an arbitrary String representation of the list, which will probably change. The "proper" way to check this would be to check the values in the list. I.e., instead of checking the string representation, you should check all your post conditions seperatly:

  • The first value is 1

  • The previous value doesn't exist (Does whatever you want to happen on error)

  • The next value does the same as the previous value

  • The size is 1

  • ...

    Of course for the methods that support this you will have to have separate unit tests.

Sign up to request clarification or add additional context in comments.

2 Comments

@Quirlom Oh! So basically, I check if self.list1.head==self.node1. And then check if self.list1.head.next==None. That way, I verify that node1 is in fact the first value (and only value, because I'm currently just creating a singly linked list so I don't think I need to check the previous value). I also don't have to rely on another function this way. Awesome, thanks. On a side note, even though you provided the correct answer already, can you still check the "Edit 2" section of my post and see if the solution I came up with is correct as well?
@user2719875 Looks fine :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.