diff --git a/exercises/binary-search-tree/.meta/template.j2 b/exercises/binary-search-tree/.meta/template.j2 new file mode 100644 index 00000000000..518d5ceda03 --- /dev/null +++ b/exercises/binary-search-tree/.meta/template.j2 @@ -0,0 +1,68 @@ +{%- import "generator_macros.j2" as macros with context -%} + +{%- macro build_tree(tree_obj) -%} +{%- if tree_obj is none -%} +None +{%- else -%} +TreeNode("{{ tree_obj["data"] }}", + {{- build_tree(tree_obj["left"]) -}}, + {{- build_tree(tree_obj["right"]) -}}) +{%- endif -%} +{%- endmacro -%} + +{%- macro test_case(case) %} + def test_{{ case["description"] | to_snake }}(self): + {%- set prop = case["property"] -%} + {%- set tree_data = case["input"]["treeData"] -%} + {%- set expected = case["expected"] -%} + {%- if expected is mapping %} + {%- set assertion = "assertTreeEqual" %} + expected = {{ build_tree(expected) }} + {%- else %} + {%- set assertion = "assertEqual" %} + expected = {{ expected }} + {%- endif %} + self.{{ assertion }}(BinarySearchTree({{ tree_data }}).{{ prop | to_snake }}(),expected) +{%- endmacro -%} + +{{ macros.header (imports=["BinarySearchTree", "TreeNode"]) }} + +class {{ exercise | camel_case }}Test(unittest.TestCase): +{%- for case in cases %} + {%- if "cases" in case %} + {%- for subcase in case["cases"] %} + {{ test_case(subcase) }} + {%- endfor %} + {%- else -%} + {{ test_case(case) }} + {%- endif %} +{%- endfor %} + + # Utilities + def assertTreeEqual(self, tree_one, tree_two): + try: + self.compare_tree(tree_one, tree_two) + except AssertionError: + raise AssertionError("{} != {}".format(tree_one, tree_two)) + + def compare_tree(self, tree_one, tree_two): + self.assertEqual(tree_one.data, tree_two.data) + + # Compare left tree nodes + if tree_one.left and tree_two.left: + self.compare_tree(tree_one.left, tree_two.left) + elif tree_one.left is None and tree_two.left is None: + pass + else: + raise AssertionError + + # Compare right tree nodes + if tree_one.right and tree_two.right: + self.compare_tree(tree_one.right, tree_two.right) + elif tree_one.right is None and tree_two.right is None: + pass + else: + raise AssertionError + + +{{ macros.footer() }} diff --git a/exercises/binary-search-tree/binary_search_tree.py b/exercises/binary-search-tree/binary_search_tree.py index 6f025157a50..dac1b98b31c 100644 --- a/exercises/binary-search-tree/binary_search_tree.py +++ b/exercises/binary-search-tree/binary_search_tree.py @@ -1,5 +1,5 @@ class TreeNode: - def __init__(self, data, left, right): + def __init__(self, data, left=None, right=None): self.data = None self.left = None self.right = None diff --git a/exercises/binary-search-tree/binary_search_tree_test.py b/exercises/binary-search-tree/binary_search_tree_test.py index 658bcaa296b..3b443abcd87 100644 --- a/exercises/binary-search-tree/binary_search_tree_test.py +++ b/exercises/binary-search-tree/binary_search_tree_test.py @@ -2,70 +2,56 @@ from binary_search_tree import BinarySearchTree, TreeNode - # Tests adapted from `problem-specifications//canonical-data.json` @ v1.0.0 -class BinarySearchTreeTest(unittest.TestCase): +class BinarySearchTreeTest(unittest.TestCase): def test_data_is_retained(self): - expected = TreeNode('4', None, None) - self.assertTreeEqual(BinarySearchTree(['4']).data(), expected) + expected = TreeNode("4", None, None) + self.assertTreeEqual(BinarySearchTree(["4"]).data(), expected) - # Test inserting data at proper node - def test_smaller_data_at_left_node(self): - expected = TreeNode('4', TreeNode('2', None, None), None) - self.assertTreeEqual(BinarySearchTree(['4', '2']).data(), expected) + def test_smaller_number_at_left_node(self): + expected = TreeNode("4", TreeNode("2", None, None), None) + self.assertTreeEqual(BinarySearchTree(["4", "2"]).data(), expected) def test_same_number_at_left_node(self): - expected = TreeNode('4', TreeNode('4', None, None), None) - self.assertTreeEqual(BinarySearchTree(['4', '4']).data(), expected) + expected = TreeNode("4", TreeNode("4", None, None), None) + self.assertTreeEqual(BinarySearchTree(["4", "4"]).data(), expected) def test_greater_number_at_right_node(self): - expected = TreeNode('4', None, TreeNode('5', None, None)) - self.assertTreeEqual(BinarySearchTree(['4', '5']).data(), expected) + expected = TreeNode("4", None, TreeNode("5", None, None)) + self.assertTreeEqual(BinarySearchTree(["4", "5"]).data(), expected) def test_can_create_complex_tree(self): expected = TreeNode( - '4', - TreeNode( - '2', - TreeNode('1', None, None), - TreeNode('3', None, None) - ), - TreeNode( - '6', - TreeNode('5', None, None), - TreeNode('7', None, None) - ) + "4", + TreeNode("2", TreeNode("1", None, None), TreeNode("3", None, None)), + TreeNode("6", TreeNode("5", None, None), TreeNode("7", None, None)), ) self.assertTreeEqual( - BinarySearchTree(['4', '2', '6', '1', '3', '5', '7']).data(), - expected + BinarySearchTree(["4", "2", "6", "1", "3", "5", "7"]).data(), expected ) - # Test can sort data def test_can_sort_single_number(self): - self.assertEqual(BinarySearchTree(['2']).sorted_data(), ['2']) + expected = ["2"] + self.assertEqual(BinarySearchTree(["2"]).sorted_data(), expected) def test_can_sort_if_second_number_is_smaller_than_first(self): - self.assertEqual( - BinarySearchTree(['2', '1']).sorted_data(), ['1', '2'] - ) + expected = ["1", "2"] + self.assertEqual(BinarySearchTree(["2", "1"]).sorted_data(), expected) def test_can_sort_if_second_number_is_same_as_first(self): - self.assertEqual( - BinarySearchTree(['2', '2']).sorted_data(), ['2', '2'] - ) + expected = ["2", "2"] + self.assertEqual(BinarySearchTree(["2", "2"]).sorted_data(), expected) def test_can_sort_if_second_number_is_greater_than_first(self): - self.assertEqual( - BinarySearchTree(['2', '3']).sorted_data(), ['2', '3'] - ) + expected = ["2", "3"] + self.assertEqual(BinarySearchTree(["2", "3"]).sorted_data(), expected) def test_can_sort_complex_tree(self): + expected = ["1", "2", "3", "5", "6", "7"] self.assertEqual( - BinarySearchTree(['2', '1', '3', '6', '7', '5']).sorted_data(), - ['1', '2', '3', '5', '6', '7'] + BinarySearchTree(["2", "1", "3", "6", "7", "5"]).sorted_data(), expected ) # Utilities @@ -95,5 +81,5 @@ def compare_tree(self, tree_one, tree_two): raise AssertionError -if __name__ == '__main__': +if __name__ == "__main__": unittest.main()