Python Testing¶
Testing Notes¶
Create a file to run your test on
Import the unittest package and the function you want to test from your file
import unittest
from [file name] import [function name]
Create a class that inherits from unittest.TestCase that will test your function
class TestFunction(unittest.TestCase):
Create a method that tests a specific instance of the function
def test_example(self):
Use the following methods to check if the expected output of a function matches with the corresponding input
.assertEqual(a, b) - Checks if a is equal to b
.assertNotEqual(a, b) - Checks if a is unequal to b
.assertTrue(x) - Checks if x is true
.assertFalse(x) - Checks if x is false
# Example using the "add()" function:
self.assertEqual(add(2,5), 7)
To run through multiple instances, create a for loop and then create a subset using unittest’s built in method
for a in [2, 4, 6, -8, -10, -12]:
with self.subTest(a=a):
self.assertTrue(isEven(a))
Once you’ve created all the methods to test all types of instances, run unittest.main in main
if __name__ == "__main__":
unittest.main()
This should give you the results of the test and any errors that don’t match the intended result
AI Queue Management Example¶
class Queue:
"""
A simple Queue implementation using a Python list.
Operates on a First-In, First-Out (FIFO) principle.
"""
def __init__(self):
# The list will hold the queue elements.
# The 'front' of the queue is index 0.
self.items = []
def is_empty(self):
"""Checks if the queue is empty."""
return len(self.items) == 0
def enqueue(self, item):
"""Adds an item to the rear of the queue."""
# Using insert(0, item) to add to the *end* for a list-based queue,
# where the *front* will be the pop() end (index -1 or 0).
# We'll use append() and pop(0) for clear FIFO with lists.
# New items go to the end (rear).
self.items.append(item)
print(f"✅ Enqueued: '{item}'. Queue size: {self.size()}")
def dequeue(self):
"""Removes and returns the item from the front of the queue (FIFO)."""
if self.is_empty():
print("❌ Error: Cannot dequeue. The queue is empty.")
return None
# pop(0) removes the item at the *front* (index 0)
dequeued_item = self.items.pop(0)
print(f"➡️ Dequeued: '{dequeued_item}'. Queue size: {self.size()}")
return dequeued_item
def peek(self):
"""Returns the item at the front of the queue without removing it."""
if self.is_empty():
print("👀 Peek: The queue is empty.")
return None
# The item at the front is at index 0
return self.items[0]
def size(self):
"""Returns the number of items in the queue."""
return len(self.items)
def display(self):
"""Displays the current state of the queue."""
if self.is_empty():
print("Queue: [Empty]")
else:
# Displaying from front to rear
print(f"Queue (Front -> Rear): {self.items}")
if __name__ == '__main__':
# --- Demonstration of the Queue ---
print("--- Initializing Queue ---")
# Create a new queue instance
service_queue = Queue()
# 1. Check initial state
service_queue.display()
print(f"Is the queue empty? {service_queue.is_empty()}")
print("-" * 25)
# 2. Enqueue some customers/elements
print("--- Enqueue Operations ---")
service_queue.enqueue("Customer A")
service_queue.enqueue("Customer B")
service_queue.enqueue("Customer C")
service_queue.display()
print("-" * 25)
# 3. Peek at the front element
print("--- Peek Operation ---")
front_item = service_queue.peek()
if front_item:
print(f"📌 Next in line (Peek): '{front_item}'")
service_queue.display() # Queue remains unchanged
print("-" * 25)
# 4. Dequeue elements (FIFO)
print("--- Dequeue Operations (Serving Customers) ---")
service_queue.dequeue() # Should be Customer A
service_queue.dequeue() # Should be Customer B
service_queue.display()
print("-" * 25)
# 5. Enqueue another element while others are waiting
print("--- More Enqueue/Dequeue ---")
service_queue.enqueue("Customer D")
service_queue.display()
service_queue.dequeue() # Should be Customer C (next FIFO)
service_queue.dequeue() # Should be Customer D
print("-" * 25)
# 6. Attempt to dequeue from an empty queue
print("--- Empty Queue Check ---")
service_queue.dequeue()
service_queue.display()
AI Testing Example¶
import unittest
# Import the Queue class from the separate queue implementation file
from queuemanagement import Queue
class QueueTest(unittest.TestCase):
"""
A testing suite for the Queue class using the unittest framework.
"""
def setUp(self):
"""Set up a fresh Queue instance before each test method."""
self.queue = Queue()
def test_initial_state(self):
"""Test that a new queue starts empty and has size 0."""
self.assertTrue(self.queue.is_empty(), "New queue should be empty.")
self.assertEqual(self.queue.size(), 0, "New queue size should be 0.")
def test_enqueue_and_size(self):
"""Test adding elements and verifying the size increases correctly."""
self.queue.enqueue("Task 1")
self.assertFalse(self.queue.is_empty(), "Queue should not be empty after enqueue.")
self.assertEqual(self.queue.size(), 1, "Size should be 1 after one enqueue.")
self.queue.enqueue("Task 2")
self.assertEqual(self.queue.size(), 2, "Size should be 2 after two enqueues.")
def test_dequeue_fifo_principle(self):
"""
Crucial test: Verify that the First-In, First-Out (FIFO) principle is enforced.
"""
# First In
self.queue.enqueue("A")
self.queue.enqueue("B")
self.queue.enqueue("C")
# First Out
dequeued_a = self.queue.dequeue()
self.assertEqual(dequeued_a, "A", "The first element dequeued must be 'A' (FIFO).")
self.assertEqual(self.queue.size(), 2, "Size should decrease after dequeue.")
dequeued_b = self.queue.dequeue()
self.assertEqual(dequeued_b, "B", "The second element dequeued must be 'B'.")
dequeued_c = self.queue.dequeue()
self.assertEqual(dequeued_c, "C", "The third element dequeued must be 'C'.")
self.assertTrue(self.queue.is_empty(), "Queue should be empty after all items are removed.")
def test_peek_functionality(self):
"""Test peek returns the front element without removing it."""
self.queue.enqueue(10)
self.queue.enqueue(20)
# Peek at 10
front_element = self.queue.peek()
self.assertEqual(front_element, 10, "Peek should return the front element (10).")
# Check that size and state are unchanged
self.assertEqual(self.queue.size(), 2, "Size should remain 2 after peek.")
self.assertEqual(self.queue.dequeue(), 10, "Dequeue should still return 10.")
def test_dequeue_on_empty(self):
"""Test that dequeueing an empty queue returns None and doesn't crash."""
result = self.queue.dequeue()
self.assertIsNone(result, "Dequeue on empty queue should return None.")
self.assertTrue(self.queue.is_empty(), "Dequeue on empty queue should not change state.")
def test_peek_on_empty(self):
"""Test that peeking an empty queue returns None."""
result = self.queue.peek()
self.assertIsNone(result, "Peek on empty queue should return None.")
self.assertTrue(self.queue.is_empty(), "Peek on empty queue should not change state.")
def test_mixed_enqueue_and_dequeue(self):
"""Test a sequence of mixed operations to ensure consistency."""
self.queue.enqueue("A")
self.queue.dequeue() # A is removed
self.queue.enqueue("B")
self.queue.enqueue("C")
self.assertEqual(self.queue.dequeue(), "B", "B should be the next item (FIFO).")
self.queue.enqueue("D")
self.assertEqual(self.queue.peek(), "C", "C should be the front item.")
self.assertEqual(self.queue.size(), 2, "Size should be 2 (C and D).")
if __name__ == '__main__':
# To run the tests, call: unittest.main()
# We use exit=False here to allow execution in environments that might restrict sys.exit()
print("Running Queue Unit Tests...\n" + "="*30)
unittest.main(argv=['first-arg-is-ignored'], exit=False)
print("\n" + "="*30)
print("Test execution complete.")
AI Explanation¶
I used the standard unittest library to create a robust suite. Here is a breakdown of what each test case verifies:
setUp(self): This method runs before every single test. It ensures we start with a brand-new, empty Queue instance (self.queue) for consistency.
test_initial_state: Verifies that a newly created queue is correctly reported as empty and has a size of zero.
test_enqueue_and_size: Confirms that the enqueue operation successfully adds an item, and the size() and is_empty() methods update their state correctly.
test_dequeue_fifo_principle: This is the most critical test. It enqueues three elements (“A”, “B”, “C”) and checks that when dequeue is called, they are returned in the exact same order they were added (A then B then C), ensuring the FIFO behavior.
test_peek_functionality: Ensures that peek() correctly identifies the front element but does not remove it, leaving the queue size and state unchanged.
test_dequeue_on_empty: Handles the edge case where a user attempts to remove an item from an empty queue, verifying the function returns None and the program doesn’t crash.
test_peek_on_empty: Handles the edge case where a user attempts to peek at an empty queue, verifying the function returns None.
test_mixed_enqueue_and_dequeue: Tests a more realistic scenario involving alternating additions and removals to ensure the internal state remains consistent across complex operations.
Running Sum Class (Example Program)¶
class RunningSum:
def __init__(self):
self.total = 0
def add(self, value):
if type(value) == int:
print("%s added!" % str(value))
self.total += value
elif type(value) == list:
for a in value:
if type(a) == int:
print("%s added!" % str(a))
self.total += a
else:
print("Error! Invalid Input for: %s" % str(a))
else:
print("Error! Invalid Input for: %s" % str(value))
def subtract(self, value):
if type(value) == int:
print("%s subtracted" % str(value))
self.total -= value
elif type(value) == list:
for a in value:
if type(a) == int:
print("%s subtracted" % str(a))
self.total -= a
else:
print("Error! Invalid Input for: %s" % str(a))
else:
print("Error! Invalid Input for: %s" % str(value))
if self.total < 0:
print("Action hit 0! Total set to 0")
self.total = 0
def clear(self):
print("Total Cleared.")
self.total = 0
def returnTotal(self):
print("Current total: %s" % str(self.total))
return self.total
if __name__ == '__main__':
total1 = RunningSum()
total1.returnTotal()
print("-" *5)
total1.add(3)
total1.add(4)
total1.add(8)
total1.returnTotal()
print("-" *5)
total1.add([6,1,2,66,3,23,6,21,1])
total1.returnTotal()
print("-" *5)
total1.subtract(5)
total1.subtract(7)
total1.subtract(2)
total1.subtract(12)
total1.subtract(3)
total1.returnTotal()
print("-" *5)
total1.subtract([20,30,40])
total1.returnTotal()
print("-" *5)
total1.subtract(1200)
total1.returnTotal()
print("-" *5)
total1.add(3)
total1.add(4)
total1.add(8)
total1.returnTotal()
total1.clear()
total1.returnTotal()
Testing Running Sum¶
import unittest
from runningsum import RunningSum
class TestFunction(unittest.TestCase):
def setUp(self):
self.run = RunningSum()
def test_default_0(self):
self.assertEqual(self.run.returnTotal(), 0)
def test_add_int(self):
self.run.add(6)
self.assertEqual(self.run.returnTotal(), 6)
def test_add_float(self):
self.run.add(3/2)
self.assertEqual(self.run.returnTotal(), 0)
def test_add_error(self):
self.run.add("21")
self.assertEqual(self.run.returnTotal(), 0)
def test_add_list(self):
self.run.add([1,2,3,4,11])
self.assertEqual(self.run.returnTotal(), 21)
def test_add_list_error(self):
self.run.add(["a", "b", "c", "d"])
self.assertEqual(self.run.returnTotal(), 0)
def test_add_list_mixed(self):
self.run.add([21, 0.4, "oooooh", 2])
self.assertEqual(self.run.returnTotal(), 23)
def test_subtract_int(self):
self.run.add(100)
self.run.subtract(2)
self.assertEqual(self.run.returnTotal(), 98)
def test_subtract_float(self):
self.run.add(100)
self.run.subtract(979/10)
self.assertEqual(self.run.returnTotal(), 100)
def test_subtract_error(self):
self.run.add(100)
self.run.subtract("21")
self.assertEqual(self.run.returnTotal(), 100)
def test_subtract_list(self):
self.run.add(100)
self.run.subtract([1,2,3,4,5])
self.assertEqual(self.run.returnTotal(), 85)
def test_subtract_list_error(self):
self.run.add(100)
self.run.subtract(["a", "b", "c", "d"])
self.assertEqual(self.run.returnTotal(), 100)
def test_subtract_list_mixed(self):
self.run.add(100)
self.run.subtract([21, 0.4, "oooooh", 2])
self.assertEqual(self.run.returnTotal(), 77)
def test_subtract_below_0(self):
self.run.add(100)
self.run.subtract(200)
self.assertEqual(self.run.returnTotal(), 0)
def test_clear(self):
self.run.add(100)
self.run.clear()
self.assertEqual(self.run.returnTotal(), 0)
if __name__ == '__main__':
unittest.main()