def test_delete_root_node_two_children(self):
        """Test to ensure the delete method correctly
        deletes a root node that has two children.
        """
        #Tree should look like this
        #        23
        #     12     34
        #   9   15      45
        # 8                56

        bst = BinarySearchTree()
        self.assertEqual(bst.size, 0)
        self.assertEqual(bst.get_height(), -1)

        nodes = [23, 12, 34, 9, 15, 45, 56, 8]
        #add nodes
        for node in nodes:
            bst.insert(node)
        self.assertEqual(bst.size, 8)
        self.assertEqual(bst.get_height(), 3)

        bst.delete(23)
        self.assertEqual(bst.size, 7)
        self.assertEqual(bst.get_height(), 3)
        self.assertIsNone(bst.search(23))
        self.assertEqual(bst.root.data, 34)
    def test_delete_root_node_left_child(self):
        """Test to delete a root node with only one child
        that is the left child.
        """
        #Tree should look like this
        #           56
        #          45
        #         34
        #       23

        bst = BinarySearchTree()
        self.assertEqual(bst.size, 0)
        self.assertEqual(bst.get_height(), -1)

        nodes = [56, 45, 34, 23]
        #add nodes
        for node in nodes:
            bst.insert(node)
        self.assertEqual(bst.size, 4)
        self.assertEqual(bst.get_height(), 3)

        #root has only a right child
        bst.delete(56)
        self.assertEqual(bst.size, 3)
        self.assertEqual(bst.get_height(), 2)
        self.assertIsNone(bst.search(56))
        self.assertEqual(bst.root.data, 45)
    def test_delete_node_one_child(self):
        """Test to delete a node that has only one child."""
        #Tree should look like this
        #        23
        #     12     34
        #   9   15      45
        # 8                56

        bst = BinarySearchTree()
        self.assertEqual(bst.size, 0)
        self.assertEqual(bst.get_height(), -1)
        nodes = [23, 12, 34, 9, 15, 45, 56, 8]
        #add nodes
        for node in nodes:
            bst.insert(node)
        self.assertEqual(bst.size, 8)
        self.assertEqual(bst.get_height(), 3)

        #delete node that just has a left child
        bst.delete(9)
        self.assertEqual(bst.size, 7)
        self.assertEqual(bst.get_height(), 3)
        self.assertIsNone(bst.search(9))

        #delete node that just has a right child
        bst.delete(45)
        self.assertEqual(bst.size, 6)
        self.assertEqual(bst.get_height(), 2)
        self.assertIsNone(bst.search(45))
    def test_delete_leaf_node(self):
        """Test that the delete method functions correctly
        when deleting a leaf node.
        """
        #Tree should look like this
        #        23
        #     12     34
        #   9   15      45
        #                 56

        bst = BinarySearchTree()
        self.assertEqual(bst.size, 0)
        self.assertEqual(bst.get_height(), -1)

        nodes = [23, 12, 34, 9, 15, 45, 56]
        #add nodes
        for node in nodes:
            bst.insert(node)
        self.assertEqual(bst.size, 7)
        self.assertEqual(bst.get_height(), 3)

        #Case 1: Deleting a leaf node
        bst.delete(56)
        self.assertEqual(bst.size, 6)
        self.assertEqual(bst.get_height(), 2)
        self.assertIsNone(bst.search(7))
    def test_delete_node_not_in_tree(self):
        """Test to ensure that the tree isn't altered if the 
        delete method is called and the node doesn't exist
        """

        #Tree should look like this
        #        23
        #     12     34
        #   9   15      45
        #                 56

        bst = BinarySearchTree()
        self.assertEqual(bst.size, 0)
        self.assertEqual(bst.get_height(), -1)

        nodes = [23, 12, 34, 9, 15, 45, 56]
        #add nodes
        for node in nodes:
            bst.insert(node)
        self.assertEqual(bst.size, 7)
        self.assertEqual(bst.get_height(), 3)

        #try deleting a node that doesn't exist
        self.assertEqual(bst.get_height(), 3)
        bst.delete(145)
        self.assertEqual(bst.size, 7)
        self.assertEqual(bst.get_height(), 3)
 def test_delete_node_from_empty_tree(self):
     """Test to ensure that the tree isn't altered if the 
     delete method is called when the tree is empty.
     """
     bst = BinarySearchTree()
     self.assertEqual(bst.size, 0)
     self.assertEqual(bst.get_height(), -1)
     bst.delete(12)
     self.assertEqual(bst.size, 0)
    def test_delete_root_as_leaf(self):
        """Test to ensure that the delete method works properly
        when the root is the only node in the tree.
        """
        bst = BinarySearchTree()
        self.assertEqual(bst.size, 0)
        self.assertEqual(bst.get_height(), -1)

        bst.insert(12)
        self.assertEqual(bst.size, 1)
        self.assertEqual(bst.get_height(), 0)

        root = bst.search(12)
        self.assertEqual(root.data, 12)

        bst.delete(12)
        self.assertEqual(bst.size, 0)
        self.assertEqual(bst.get_height(), -1)
        self.assertIsNone(bst.root)
    def test_delete_node_two_children(self):
        """Test to delete a node with two children."""
        #Tree should look like this
        #        23
        #     12     34
        #   9   15      45
        # 8                56

        bst = BinarySearchTree()
        self.assertEqual(bst.size, 0)
        self.assertEqual(bst.get_height(), -1)

        nodes = [23, 12, 34, 9, 15, 45, 56, 8]
        #add nodes
        for node in nodes:
            bst.insert(node)
        self.assertEqual(bst.size, 8)
        self.assertEqual(bst.get_height(), 3)

        bst.delete(12)
        self.assertEqual(bst.size, 7)
        self.assertEqual(bst.get_height(), 3)
        self.assertIsNone(bst.search(12))