1+ import unittest
2+ from unittest .mock import patch
3+ import io
4+ import os
5+ import importlib .util
6+
7+ # Absolute path to Heap-Sort.py
8+ file_path = os .path .join (
9+ os .path .dirname (__file__ ), ".." ,
10+ "math" , "Heap-Sort" , "Heap-Sort.py"
11+ )
12+ file_path = os .path .abspath (file_path )
13+
14+ # Load module dynamically
15+ spec = importlib .util .spec_from_file_location ("heap_sort_module" , file_path )
16+ heap_sort_module = importlib .util .module_from_spec (spec )
17+ spec .loader .exec_module (heap_sort_module )
18+
19+ heap_sort = heap_sort_module .heap_sort
20+ main = heap_sort_module .main
21+
22+
23+ class TestHeapSort (unittest .TestCase ):
24+
25+ def test_heap_sort_ascending (self ):
26+ self .assertEqual (heap_sort ([64 , 34 , 25 , 12 , 22 , 11 , 90 ]), [11 , 12 , 22 , 25 , 34 , 64 , 90 ])
27+ self .assertEqual (heap_sort ([5 , 1 , 4 , 2 , 8 ]), [1 , 2 , 4 , 5 , 8 ])
28+
29+ def test_heap_sort_descending (self ):
30+ self .assertEqual (heap_sort ([64 , 34 , 25 , 12 , 22 , 11 , 90 ], reverse = True ), [90 , 64 , 34 , 25 , 22 , 12 , 11 ])
31+ self .assertEqual (heap_sort ([5 , 1 , 4 , 2 , 8 ], reverse = True ), [8 , 5 , 4 , 2 , 1 ])
32+
33+ def test_heap_sort_empty_and_single_item (self ):
34+ self .assertEqual (heap_sort ([]), [])
35+ self .assertEqual (heap_sort ([42 ]), [42 ])
36+
37+ def test_heap_sort_negative_integers (self ):
38+ self .assertEqual (heap_sort ([- 5 , - 1 , - 10 , 0 , 5 ]), [- 10 , - 5 , - 1 , 0 , 5 ])
39+ self .assertEqual (heap_sort ([- 5 , - 1 , - 10 , 0 , 5 ], reverse = True ), [5 , 0 , - 1 , - 5 , - 10 ])
40+
41+ def test_heap_sort_already_sorted (self ):
42+ self .assertEqual (heap_sort ([1 , 2 , 3 , 4 , 5 ]), [1 , 2 , 3 , 4 , 5 ])
43+ self .assertEqual (heap_sort ([5 , 4 , 3 , 2 , 1 ], reverse = True ), [5 , 4 , 3 , 2 , 1 ])
44+
45+ def test_heap_sort_with_duplicates (self ):
46+ self .assertEqual (heap_sort ([5 , 3 , 8 , 3 , 9 , 1 , 5 ]), [1 , 3 , 3 , 5 , 5 , 8 , 9 ])
47+
48+ def test_heap_sort_does_not_mutate_original (self ):
49+ original = [5 , 3 , 1 , 4 , 2 ]
50+ original_copy = original .copy ()
51+ heap_sort (original )
52+ self .assertEqual (original , original_copy )
53+
54+ @patch ('builtins.input' )
55+ @patch ('sys.stdout' , new_callable = io .StringIO )
56+ def test_main_flow_ascending (self , mock_stdout , mock_input ):
57+ mock_input .side_effect = ["64 34 25" , "1" , "n" ]
58+ main ()
59+ output = mock_stdout .getvalue ()
60+ self .assertIn ("Original list: [64, 34, 25]" , output )
61+ self .assertIn ("Sorted list (Ascending): [25, 34, 64]" , output )
62+
63+ @patch ('builtins.input' )
64+ @patch ('sys.stdout' , new_callable = io .StringIO )
65+ def test_main_flow_invalid_inputs (self , mock_stdout , mock_input ):
66+ mock_input .side_effect = ["" , "64 abc 25" , "64 34 25" , "3" , "64 34 25" , "1" , "y" , "12 11" , "2" , "n" ]
67+ main ()
68+ output = mock_stdout .getvalue ()
69+ self .assertIn ("Error: Input cannot be empty!" , output )
70+ self .assertIn ("Error: Please enter valid integers only." , output )
71+ self .assertIn ("Invalid sorting choice! Please select 1 or 2." , output )
72+ self .assertIn ("Sorted list (Ascending): [25, 34, 64]" , output )
73+ self .assertIn ("Sorted list (Descending): [12, 11]" , output )
74+
75+
76+ if __name__ == '__main__' :
77+ unittest .main ()
0 commit comments