Level based Representation of a Binary Tree - Tests with unittest

Creating tests package

Let's add some tests load function. We will use the builtin unittest package. Follow the following steps:

Create a new package tests. In other words, create a new directory named tests alongside the tree package and also create a new empty file __init__.py inside this directory

Directory structure so far
 project 
   ├── tree 
         ├── __init__.py
         ├── node.py
         ├── actions.py
   ├── tests
         ├── __init__.py

Now, Create a module load.py which contains our test case. we also import the load function, we want to test in this test case

tests/load.py
 import unittest
 from tree import load
 
 class TestLoad(unittest.TestCase):
   ...

Writing assert functions

In the tests, we should check whether the actual nodes loaded by the load function are equal to the expected nodes.

What should we test?

First, We need to test that the data stored in the actual is equal to the data stored in the expected node.

We also need to test whether the actual node has the same children as the expected node. There are four cases for that:

  • The node has both left and right children.
  • The node has a left child but does not have a right child.
  • The node has a right child but does not have a left child.
  • The node is a leaf - In other words, it does not have any children.

Let's create assert functions for the above cases, we call those cases assertBoth, assertLeft, assertRight, assertLeaf

tests/load.py - assert functions
 ...
 class TestLoad(unittest.TestCase):

   def assertBoth (self, tree, data):
       self.assertEqual   (tree.data, data)
       self.assertNotEqual(tree.left, None)
       self.assertNotEqual(tree.right, None)

   def assertLeft (self, tree, data):
       self.assertEqual   (tree.data, data)
       self.assertNotEqual(tree.left, None)
       self.assertEqual   (tree.right, None)

   def assertRight(self, tree, data):
       self.assertEqual   (tree.data, data)
       self.assertEqual   (tree.left, None)
       self.assertNotEqual(tree.right,None)

   def assertLeaf (self, tree, data):
       self.assertEqual(tree.data, data)
       self.assertEqual(tree.left, None)
       self.assertEqual(tree.right, None)

Writing tests

Let's write some test to level-based representation of binary tree. For simplicity, the data in tested lists will be their position in the list.

It is important to call the test in significant name. We use test followed by items of the list separated by _. we also use x instead of None to make the the name concise. This way, we can easilly see what the test function is about.

The simplest list is the the empty list

binary tree graph []
tests/load.py - test []
 def test_load_empty(self):
     tree = load([])
     self.assertEqual(tree, None)    

Now, let's create tests for the following trees

binary tree graph [0]
tests/load.py - test [0]
 def test_load_0(self):
     tree = load([0])
     self.assertLeaf(tree,0)
binary tree graph [0,1]
tests/load.py - test [0,1]
 def test_load_0_1(self):
     tree = load([0,1])
     self.assertLeft(tree, 0)
     self.assertLeaf(tree.left ,1 )
binary tree graph [0,None,2]
tests/load.py - test [0,None,2]
 def test_load_0_x_2(self):
     tree = load([0,None,2])
     self.assertRight(tree, 0)
     self.assertLeaf(tree.right ,2 )
binary tree graph [0,1,2,None,4,5]
tests/load.py - test [0,1,2,None,4,5]
 def test_load_0_1_2_x_4_5(self):
     tree = load([0,1,2,None,4,5])
     # level 0
     self.assertBoth (tree            , 0)
     # level 1
     self.assertRight(tree.left       , 1)
     self.assertLeft (tree.right      , 2)
     # level 2
     self.assertLeaf (tree.left.right , 4)
     self.assertLeaf (tree.right.left , 5)

In the next part we run the tests and understand the report generated by unittest module.