Repository: keon/algorithms
Pull request #245 (2018-04-21 20:38:33)

Add heap and stack to test
PR to add test_heap and test_stack to tests.

danghai: I have updated it! 

Patch:
diff --git a/array/__init__.py b/arrays/__init__.py
similarity index 100%
rename from array/__init__.py
rename to arrays/__init__.py
diff --git a/array/delete_nth.py b/arrays/delete_nth.py
similarity index 100%
rename from array/delete_nth.py
rename to arrays/delete_nth.py
diff --git a/array/flatten.py b/arrays/flatten.py
similarity index 100%
rename from array/flatten.py
rename to arrays/flatten.py
diff --git a/array/garage.py b/arrays/garage.py
similarity index 100%
rename from array/garage.py
rename to arrays/garage.py
diff --git a/array/josephus_problem.py b/arrays/josephus_problem.py
similarity index 100%
rename from array/josephus_problem.py
rename to arrays/josephus_problem.py
diff --git a/array/longest_non_repeat.py b/arrays/longest_non_repeat.py
similarity index 100%
rename from array/longest_non_repeat.py
rename to arrays/longest_non_repeat.py
diff --git a/array/merge_intervals.py b/arrays/merge_intervals.py
similarity index 100%
rename from array/merge_intervals.py
rename to arrays/merge_intervals.py
diff --git a/array/missing_ranges.py b/arrays/missing_ranges.py
similarity index 100%
rename from array/missing_ranges.py
rename to arrays/missing_ranges.py
diff --git a/array/move_zeros_to_end.py b/arrays/move_zeros_to_end.py
similarity index 100%
rename from array/move_zeros_to_end.py
rename to arrays/move_zeros_to_end.py
diff --git a/array/plus_one.py b/arrays/plus_one.py
similarity index 100%
rename from array/plus_one.py
rename to arrays/plus_one.py
diff --git a/array/rotate_array.py b/arrays/rotate_array.py
similarity index 100%
rename from array/rotate_array.py
rename to arrays/rotate_array.py
diff --git a/array/summary_ranges.py b/arrays/summary_ranges.py
similarity index 100%
rename from array/summary_ranges.py
rename to arrays/summary_ranges.py
diff --git a/array/three_sum.py b/arrays/three_sum.py
similarity index 100%
rename from array/three_sum.py
rename to arrays/three_sum.py
diff --git a/array/two_sum.py b/arrays/two_sum.py
similarity index 100%
rename from array/two_sum.py
rename to arrays/two_sum.py
diff --git a/heap/__init__.py b/heap/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/heap/binary_heap.py b/heap/binary_heap.py
index 24e52fc..5119a03 100644
--- a/heap/binary_heap.py
+++ b/heap/binary_heap.py
@@ -29,7 +29,6 @@ For example remove_min() in a min heap:
 55 90 87             55  90                 55  90
 
 """
-import unittest
 from abc import ABCMeta, abstractmethod
 
 class AbstractHeap(metaclass=ABCMeta):
@@ -114,37 +113,3 @@ class BinaryHeap(AbstractHeap):
         self.heap.pop()
         self.perc_down(1)
         return ret
-
-class TestSuite(unittest.TestCase):
-    """
-        Test suite for the Binary_Heap data structures
-    """
-    def setUp(self):
-        self.min_heap = BinaryHeap()
-        self.min_heap.insert(4)
-        self.min_heap.insert(50)
-        self.min_heap.insert(7)
-        self.min_heap.insert(55)
-        self.min_heap.insert(90)
-        self.min_heap.insert(87)
-
-    def test_insert(self):
-        # Before insert 2: [0, 4, 50, 7, 55, 90, 87]
-        # After insert:  [0, 2, 50, 4, 55, 90, 87, 7]
-        self.min_heap.insert(2)
-        self.assertEqual([0, 2, 50, 4, 55, 90, 87, 7],
-                          self.min_heap.heap)
-        self.assertEqual(7, self.min_heap.currentSize)
-
-    def test_remove_min(self):
-        ret = self.min_heap.remove_min()
-        # Before remove_min : [0, 4, 50, 7, 55, 90, 87]
-        # After remove_min: [7, 50, 87, 55, 90]
-        # Test return value
-        self.assertEqual(4,ret)
-        self.assertEqual([0, 7, 50, 87, 55, 90],
-                          self.min_heap.heap)
-        self.assertEqual(5, self.min_heap.currentSize)
-
-if __name__ == "__main__":
-    unittest.main()
diff --git a/heap/skyline.py b/heap/skyline.py
index 5912add..c666703 100644
--- a/heap/skyline.py
+++ b/heap/skyline.py
@@ -34,7 +34,6 @@ There must be no consecutive horizontal lines of equal height in the output skyl
 into one in the final output as such: [...[2 3], [4 5], [12 7], ...]
 
 """
-
 import heapq
 
 def get_skyline(lrh):
@@ -59,7 +58,3 @@ def get_skyline(lrh):
         if not skyline or height != skyline[-1][1]:
             skyline += [x, height],
     return skyline
-
-buildings = [ [2, 9, 10], [3, 7, 15], [5, 12, 12], [15, 20, 10], [19, 24, 8] ]
-# [ [2 10], [3 15], [7 12], [12 0], [15 10], [20 8], [24, 0] ]
-print(get_skyline(buildings))
diff --git a/stack/is_consecutive.py b/stack/is_consecutive.py
index 6964d4f..f73ddff 100644
--- a/stack/is_consecutive.py
+++ b/stack/is_consecutive.py
@@ -16,7 +16,6 @@ Note: There are 2 solutions:
 first_is_consecutive: it uses a single stack as auxiliary storage
 second_is_consecutive: it uses a single queue as auxiliary storage
 """
-import unittest
 import collections
 
 def first_is_consecutive(stack):
@@ -57,19 +56,3 @@ def second_is_consecutive(stack):
         stack.append(q.pop())
 
     return True
-
-class TestSuite(unittest.TestCase):
-    """
-        test suite for the function (above)
-    """
-    def test_is_consecutive(self):
-        self.assertTrue(first_is_consecutive([3, 4, 5, 6, 7]))
-        self.assertFalse(first_is_consecutive([3, 4, 6, 7]))
-        self.assertFalse(first_is_consecutive([3, 2, 1]))
-
-        self.assertTrue(second_is_consecutive([3, 4, 5, 6, 7]))
-        self.assertFalse(second_is_consecutive([3, 4, 6, 7]))
-        self.assertFalse(second_is_consecutive([3, 2, 1]))
-
-if __name__ == "__main__":
-    unittest.main()
diff --git a/stack/is_sorted.py b/stack/is_sorted.py
index 9ff30f1..8824dfa 100644
--- a/stack/is_sorted.py
+++ b/stack/is_sorted.py
@@ -9,8 +9,6 @@ The function should return false
 bottom [1, 2, 3, 4, 5, 6] top
 The function should return true
 """
-import unittest
-
 def is_sorted(stack):
     storage_stack = []
     for i in range(len(stack)):
@@ -30,15 +28,3 @@ def is_sorted(stack):
         stack.append(storage_stack.pop())
 
     return True
-
-class TestSuite(unittest.TestCase):
-    """
-        test suite for the function (above)
-    """
-    def test_stutter(self):
-        # Test case: bottom [6, 3, 5, 1, 2, 4] top
-        self.assertFalse(is_sorted([6, 3, 5, 1, 2, 4]))
-        self.assertTrue(is_sorted([1, 2, 3, 4, 5, 6]))
-
-if __name__ == "__main__":
-    unittest.main()
diff --git a/stack/remove_min.py b/stack/remove_min.py
index 0426020..1cd8fc6 100644
--- a/stack/remove_min.py
+++ b/stack/remove_min.py
@@ -8,8 +8,6 @@ After remove_min(stack):
 bottom [2, 8, 3, 7, 3] top
 
 """
-import unittest
-
 def remove_min(stack):
     storage_stack = []
     if len(stack) == 0:  # Stack is empty
@@ -28,16 +26,3 @@ def remove_min(stack):
         if val != min:
             stack.append(val)
     return stack
-
-class TestSuite(unittest.TestCase):
-    """
-        test suite for the function (above)
-    """
-    def test_stutter(self):
-        # Test case: bottom [2, 8, 3, -6, 7, 3] top
-        self.assertEqual([2, 8, 3, 7, 3], remove_min([2, 8, 3, -6, 7, 3]))
-        # Test case: 2 smallest value [2, 8, 3, 7, 3]
-        self.assertEqual([4, 8, 7], remove_min([4, 8, 3, 7, 3]))
-
-if __name__ == "__main__":
-    unittest.main()
diff --git a/stack/simplify_path.py b/stack/simplify_path.py
index fba0ade..fed4385 100644
--- a/stack/simplify_path.py
+++ b/stack/simplify_path.py
@@ -10,8 +10,6 @@ path = "/a/./b/../../c/", => "/c"
 * Another corner case is the path might contain multiple slashes '/' together, such as "/home//foo/".
     In this case, you should ignore redundant slashes and return "/home/foo".
 """
-
-
 def simplify_path(path):
     """
     :type path: str
@@ -27,10 +25,3 @@ def simplify_path(path):
         elif tok not in skip:
             stack.append(tok)
     return '/' + '/'.join(stack)
-
-
-if __name__ == '__main__':
-
-    p = '/my/name/is/..//keon'
-    print(p)
-    print(simplify_path(p))
diff --git a/stack/stack.py b/stack/stack.py
index ce72139..216c264 100644
--- a/stack/stack.py
+++ b/stack/stack.py
@@ -13,10 +13,7 @@ isEmpty() tests to see whether the stack is empty.
 size() returns the number of items on the stack.
    It needs no parameters and returns an integer.
 """
-import unittest
 from abc import ABCMeta, abstractmethod
-
-
 class AbstractStack(metaclass=ABCMeta):
     """Abstract Class for Stacks."""
     def __init__(self):
@@ -133,84 +130,3 @@ class LinkedListStack(AbstractStack):
         if self.is_empty():
             raise IndexError("Stack is empty")
         return self.head.value
-
-    # optional
-    """
-    def is_empty(self):
-        return self.head is None
-    """
-
-
-class TestSuite(unittest.TestCase):
-    """
-        Test suite for the stack data structures (above)
-    """
-
-    def test_ArrayStack(self):
-        stack = ArrayStack()
-        stack.push(1)
-        stack.push(2)
-        stack.push(3)
-
-        # test __iter__()
-        it = iter(stack)
-        self.assertEqual(3, next(it))
-        self.assertEqual(2, next(it))
-        self.assertEqual(1, next(it))
-        self.assertRaises(StopIteration, next, it)
-
-        # test __len__()
-        self.assertEqual(3, len(stack))
-
-        # test __str__()
-        self.assertEqual(str(stack), "Top-> 3 2 1")
-
-        # test is_empty()
-        self.assertFalse(stack.is_empty())
-
-        # test peek()
-        self.assertEqual(3, stack.peek())
-
-        # test pop()
-        self.assertEqual(3, stack.pop())
-        self.assertEqual(2, stack.pop())
-        self.assertEqual(1, stack.pop())
-
-        self.assertTrue(stack.is_empty())
-
-    def test_LinkedListStack(self):
-        stack = LinkedListStack()
-
-        stack.push(1)
-        stack.push(2)
-        stack.push(3)
-
-        # test __iter__()
-        it = iter(stack)
-        self.assertEqual(3, next(it))
-        self.assertEqual(2, next(it))
-        self.assertEqual(1, next(it))
-        self.assertRaises(StopIteration, next, it)
-
-        # test __len__()
-        self.assertEqual(3, len(stack))
-
-        # test __str__()
-        self.assertEqual(str(stack), "Top-> 3 2 1")
-
-        # test is_empty()
-        self.assertFalse(stack.is_empty())
-
-        # test peek()
-        self.assertEqual(3, stack.peek())
-
-        # test pop()
-        self.assertEqual(3, stack.pop())
-        self.assertEqual(2, stack.pop())
-        self.assertEqual(1, stack.pop())
-
-        self.assertTrue(stack.is_empty())
-
-
-if __name__ == "__main__":
-    unittest.main()
diff --git a/stack/stutter.py b/stack/stutter.py
index 3956d33..3031499 100644
--- a/stack/stutter.py
+++ b/stack/stutter.py
@@ -11,7 +11,6 @@ Note: There are 2 solutions:
 first_stutter: it uses a single stack as auxiliary storage
 second_stutter: it uses a single queue as auxiliary storage
 """
-import unittest
 import collections
 
 def first_stutter(stack):
@@ -43,16 +42,3 @@ def second_stutter(stack):
         stack.append(val)
 
     return stack
-class TestSuite(unittest.TestCase):
-    """
-        test suite for the function (above)
-    """
-    def test_stutter(self):
-        # Test case: bottom [3, 7, 1, 14, 9] top
-        self.assertEqual([3, 3, 7, 7, 1, 1, 14, 14, 9, 9],
-                         first_stutter([3, 7, 1, 14, 9]))
-        self.assertEqual([3, 3, 7, 7, 1, 1, 14, 14, 9, 9],
-                         second_stutter([3, 7, 1, 14, 9]))
-
-if __name__ == "__main__":
-    unittest.main()
diff --git a/stack/switch_pairs.py b/stack/switch_pairs.py
index 97a9a51..f5db228 100644
--- a/stack/switch_pairs.py
+++ b/stack/switch_pairs.py
@@ -18,7 +18,6 @@ Note: There are 2 solutions:
 first_switch_pairs: it uses a single stack as auxiliary storage
 second_switch_pairs: it uses a single queue as auxiliary storage
 """
-import unittest
 import collections
 
 def first_switch_pairs(stack):
@@ -61,24 +60,3 @@ def second_switch_pairs(stack):
         stack.append(first)
 
     return stack
-
-class TestSuite(unittest.TestCase):
-    """
-        test suite for the function (above)
-    """
-    def test_switch_pairs(self):
-        # Test case: even number of values in stack
-        # bottom [3, 8, 17, 9, 1, 10] top
-        self.assertEqual([8, 3, 9, 17, 10, 1],
-                         first_switch_pairs([3, 8, 17, 9, 1, 10]))
-        self.assertEqual([8, 3, 9, 17, 10, 1],
-                         second_switch_pairs([3, 8, 17, 9, 1, 10]))
-        # Test case: odd number of values in stack
-        # bottom [3, 8, 17, 9, 1] top
-        self.assertEqual([8, 3, 9, 17, 1],
-                         first_switch_pairs([3, 8, 17, 9, 1]))
-        self.assertEqual([8, 3, 9, 17, 1],
-                         second_switch_pairs([3, 8, 17, 9, 1]))
-
-if __name__ == "__main__":
-    unittest.main()
diff --git a/stack/valid_parenthesis.py b/stack/valid_parenthesis.py
index 179c940..b62ac02 100644
--- a/stack/valid_parenthesis.py
+++ b/stack/valid_parenthesis.py
@@ -6,10 +6,6 @@ determine if the input string is valid.
 The brackets must close in the correct order,
 "()" and "()[]{}" are all valid but "(]" and "([)]" are not.
 """
-
-import unittest
-
-
 def is_valid(s: str) -> bool:
     stack = []
     dic = {")": "(",
@@ -22,20 +18,3 @@ def is_valid(s: str) -> bool:
             if not stack or dic[char] != stack.pop():
                 return False
     return not stack
-
-
-class TestSuite(unittest.TestCase):
-    """
-        test suite for the function (above)
-    """
-    def test_is_valid(self):
-
-        self.assertTrue(is_valid("[]"))
-        self.assertTrue(is_valid("[]()[]"))
-        self.assertFalse(is_valid("[[[]]"))
-        self.assertTrue(is_valid("{([])}"))
-        self.assertFalse(is_valid("(}"))
-
-
-if __name__ == "__main__":
-    unittest.main()


Test patch:
diff --git a/tests/test_array.py b/tests/test_array.py
index c02a41b..acae483 100644
--- a/tests/test_array.py
+++ b/tests/test_array.py
@@ -1,16 +1,16 @@
-from array.delete_nth import delete_nth, delete_nth_naive
-from array.flatten import flatten, flatten_iter
-from array.garage import garage
-from array.josephus_problem import josephus
-from array.longest_non_repeat import longest_non_repeat, longest_non_repeat_two
-from array.merge_intervals import Interval, merge_v2
-from array.missing_ranges import missing_ranges
-from array.move_zeros_to_end import move_zeros
-from array.plus_one import plus_one, plus_one_v2, plus_one_v3
-from array.rotate_array import rotate_v1, rotate_v2, rotate_v3
-from array.summary_ranges import summary_ranges
-from array.three_sum import three_sum
-from array.two_sum import two_sum
+from arrays.delete_nth import delete_nth, delete_nth_naive
+from arrays.flatten import flatten, flatten_iter
+from arrays.garage import garage
+from arrays.josephus_problem import josephus
+from arrays.longest_non_repeat import longest_non_repeat, longest_non_repeat_two
+from arrays.merge_intervals import Interval, merge_v2
+from arrays.missing_ranges import missing_ranges
+from arrays.move_zeros_to_end import move_zeros
+from arrays.plus_one import plus_one, plus_one_v2, plus_one_v3
+from arrays.rotate_array import rotate_v1, rotate_v2, rotate_v3
+from arrays.summary_ranges import summary_ranges
+from arrays.three_sum import three_sum
+from arrays.two_sum import two_sum
 
 import unittest
 
diff --git a/tests/test_heap.py b/tests/test_heap.py
new file mode 100644
index 0000000..c6f2c7e
--- /dev/null
+++ b/tests/test_heap.py
@@ -0,0 +1,52 @@
+from heap.binary_heap import BinaryHeap
+from heap.skyline import get_skyline
+from heap.sliding_window_max import max_sliding_window
+
+import unittest
+
+class TestBinaryHeap(unittest.TestCase):
+    """
+        Test suite for the binary_heap data structures
+    """
+    def setUp(self):
+        self.min_heap = BinaryHeap()
+        self.min_heap.insert(4)
+        self.min_heap.insert(50)
+        self.min_heap.insert(7)
+        self.min_heap.insert(55)
+        self.min_heap.insert(90)
+        self.min_heap.insert(87)
+
+    def test_insert(self):
+        # Before insert 2: [0, 4, 50, 7, 55, 90, 87]
+        # After insert:  [0, 2, 50, 4, 55, 90, 87, 7]
+        self.min_heap.insert(2)
+        self.assertEqual([0, 2, 50, 4, 55, 90, 87, 7],
+                          self.min_heap.heap)
+        self.assertEqual(7, self.min_heap.currentSize)
+
+    def test_remove_min(self):
+        ret = self.min_heap.remove_min()
+        # Before remove_min : [0, 4, 50, 7, 55, 90, 87]
+        # After remove_min: [7, 50, 87, 55, 90]
+        # Test return value
+        self.assertEqual(4,ret)
+        self.assertEqual([0, 7, 50, 87, 55, 90],
+                          self.min_heap.heap)
+        self.assertEqual(5, self.min_heap.currentSize)
+
+class TestSuite(unittest.TestCase):
+    def test_get_skyline(self):
+        buildings = [ [2, 9, 10], [3, 7, 15], [5, 12, 12], \
+                      [15, 20, 10], [19, 24, 8] ]
+        # Expect output
+        output = [ [2, 10], [3, 15], [7, 12], [12, 0], [15, 10], \
+                   [20, 8], [24, 0] ]
+        self.assertEqual(output, get_skyline(buildings))
+
+    def test_max_sliding_window(self):
+        nums = [1, 3, -1, -3, 5, 3, 6, 7]
+        self.assertEqual([3, 3, 5, 5, 6, 7], max_sliding_window(nums, 3))
+
+if __name__ == "__main__":
+    unittest.main()
diff --git a/tests/test_stack.py b/tests/test_stack.py
new file mode 100644
index 0000000..3b55ac9
--- /dev/null
+++ b/tests/test_stack.py
@@ -0,0 +1,133 @@
+from stack.is_consecutive import first_is_consecutive, second_is_consecutive
+from stack.is_sorted import is_sorted
+from stack.remove_min import remove_min
+from stack.stutter import first_stutter, second_stutter
+from stack.switch_pairs import first_switch_pairs, second_switch_pairs
+from stack.valid_parenthesis import is_valid
+from stack.simplify_path import simplify_path
+from stack.stack import ArrayStack, LinkedListStack
+
+import unittest
+class TestSuite(unittest.TestCase):
+    def test_is_consecutive(self):
+        self.assertTrue(first_is_consecutive([3, 4, 5, 6, 7]))
+        self.assertFalse(first_is_consecutive([3, 4, 6, 7]))
+        self.assertFalse(first_is_consecutive([3, 2, 1]))
+
+        self.assertTrue(second_is_consecutive([3, 4, 5, 6, 7]))
+        self.assertFalse(second_is_consecutive([3, 4, 6, 7]))
+        self.assertFalse(second_is_consecutive([3, 2, 1]))
+
+    def test_is_sorted(self):
+        # Test case: bottom [6, 3, 5, 1, 2, 4] top
+        self.assertFalse(is_sorted([6, 3, 5, 1, 2, 4]))
+        self.assertTrue(is_sorted([1, 2, 3, 4, 5, 6]))
+
+    def test_remove_min(self):
+        # Test case: bottom [2, 8, 3, -6, 7, 3] top
+        self.assertEqual([2, 8, 3, 7, 3], remove_min([2, 8, 3, -6, 7, 3]))
+        # Test case: 2 smallest value [2, 8, 3, 7, 3]
+        self.assertEqual([4, 8, 7], remove_min([4, 8, 3, 7, 3]))
+
+    def test_stutter(self):
+        # Test case: bottom [3, 7, 1, 14, 9] top
+        self.assertEqual([3, 3, 7, 7, 1, 1, 14, 14, 9, 9],
+                         first_stutter([3, 7, 1, 14, 9]))
+        self.assertEqual([3, 3, 7, 7, 1, 1, 14, 14, 9, 9],
+                         second_stutter([3, 7, 1, 14, 9]))
+
+    def test_switch_pairs(self):
+        # Test case: even number of values in stack
+        # bottom [3, 8, 17, 9, 1, 10] top
+        self.assertEqual([8, 3, 9, 17, 10, 1],
+                         first_switch_pairs([3, 8, 17, 9, 1, 10]))
+        self.assertEqual([8, 3, 9, 17, 10, 1],
+                         second_switch_pairs([3, 8, 17, 9, 1, 10]))
+        # Test case: odd number of values in stack
+        # bottom [3, 8, 17, 9, 1] top
+        self.assertEqual([8, 3, 9, 17, 1],
+                         first_switch_pairs([3, 8, 17, 9, 1]))
+        self.assertEqual([8, 3, 9, 17, 1],
+                         second_switch_pairs([3, 8, 17, 9, 1]))
+
+    def test_is_valid_parenthesis(self):
+
+        self.assertTrue(is_valid("[]"))
+        self.assertTrue(is_valid("[]()[]"))
+        self.assertFalse(is_valid("[[[]]"))
+        self.assertTrue(is_valid("{([])}"))
+        self.assertFalse(is_valid("(}"))
+
+    def test_simplify_path(self):
+        p = '/my/name/is/..//keon'
+        self.assertEqual('/my/name/keon', simplify_path(p))
+
+
+class TestStack(unittest.TestCase):
+    def test_ArrayStack(self):
+        stack = ArrayStack()
+        stack.push(1)
+        stack.push(2)
+        stack.push(3)
+
+        # test __iter__()
+        it = iter(stack)
+        self.assertEqual(3, next(it))
+        self.assertEqual(2, next(it))
+        self.assertEqual(1, next(it))
+        self.assertRaises(StopIteration, next, it)
+
+        # test __len__()
+        self.assertEqual(3, len(stack))
+
+        # test __str__()
+        self.assertEqual(str(stack), "Top-> 3 2 1")
+
+        # test is_empty()
+        self.assertFalse(stack.is_empty())
+
+        # test peek()
+        self.assertEqual(3, stack.peek())
+
+        # test pop()
+        self.assertEqual(3, stack.pop())
+        self.assertEqual(2, stack.pop())
+        self.assertEqual(1, stack.pop())
+
+        self.assertTrue(stack.is_empty())
+
+    def test_LinkedListStack(self):
+        stack = LinkedListStack()
+
+        stack.push(1)
+        stack.push(2)
+        stack.push(3)
+
+        # test __iter__()
+        it = iter(stack)
+        self.assertEqual(3, next(it))
+        self.assertEqual(2, next(it))
+        self.assertEqual(1, next(it))
+        self.assertRaises(StopIteration, next, it)
+
+        # test __len__()
+        self.assertEqual(3, len(stack))
+
+        # test __str__()
+        self.assertEqual(str(stack), "Top-> 3 2 1")
+
+        # test is_empty()
+        self.assertFalse(stack.is_empty())
+
+        # test peek()
+        self.assertEqual(3, stack.peek())
+
+        # test pop()
+        self.assertEqual(3, stack.pop())
+        self.assertEqual(2, stack.pop())
+        self.assertEqual(1, stack.pop())
+
+        self.assertTrue(stack.is_empty())
+
+if __name__ == "__main__":
+    unittest.main()