.. include:: ../global.rst *************************** Testing *************************** Unit Testing in Python ====================== Queue Management Program (Python) Here is a simple class that implements a basic **First-In, First-Out (FIFO)** queue using Python's built-in list structure. .. code-block:: python class SimpleQueueManager: """ A simple manager for a FIFO (First-In, First-Out) queue. """ def __init__(self): # The list acts as the queue, with the 'front' being index 0. self.queue = [] def enqueue(self, item): """ Adds an item to the end (rear) of the queue. """ self.queue.append(item) return f"'{item}' added to the queue." def dequeue(self): """ Removes and returns the item from the front of the queue. Raises an IndexError if the queue is empty. """ if not self.is_empty(): # Use pop(0) to remove the first element (FIFO) return self.queue.pop(0) else: return "Error: Queue is empty." def peek(self): """ Returns the item at the front of the queue without removing it. """ if not self.is_empty(): return self.queue[0] else: return "Queue is empty." def size(self): """ Returns the current number of items in the queue. """ return len(self.queue) def is_empty(self): """ Checks if the queue is currently empty. """ return self.size() == 0 # Example Usage: q = SimpleQueueManager() q.enqueue("Customer A") q.enqueue("Customer B") print(q.size()) # Output: 2 print(q.peek()) # Output: Customer A print(q.dequeue()) # Output: Customer A print(q.dequeue()) # Output: Customer B print(q.dequeue()) # Output: Error: Queue is empty. --- Testing Suite for the Queue Manager Program A comprehensive testing suite for the ``SimpleQueueManager`` should aim for **100% code coverage**, testing both the expected (**happy path**) and edge case (**error path**) behaviors of every method. We'll use Python's built-in **unittest** framework for this. Key Testing Principles * **Isolation:** Tests should be independent; running one test shouldn't affect the result of another. * **Atomicity:** Each test should focus on a single piece of functionality. * **Black Box Testing:** Focus on what the class should do, not how it does it (e.g., test ``dequeue()`` to see if it returns the correct item, not how it uses ``pop(0)``). The Test Suite Explanation .. list-table:: :widths: 20 20 40 20 :header-rows: 1 * - Test Case Category - Methods Covered - Description of Test - Expected Outcome * - Basic Operations - ``enqueue()``, ``dequeue()`` - Test adding one item, then removing it. - ``dequeue()`` returns the item added. * - FIFO Integrity - ``enqueue()``, ``dequeue()`` - Add multiple items (A, B, C) and ensure they are removed in the correct order (A, then B, then C). - Items are dequeued in the order they were enqueued. * - Empty State (Edge Case) - ``is_empty()``, ``size()`` - Test a newly instantiated queue. - ``is_empty()`` returns True, ``size()`` returns 0. * - Full/Empty Cycle - All - Add items, empty the queue, then add new items. - The queue state is correctly reset, and new operations work as expected. * - ``peek()`` Functionality - ``peek()`` - Check ``peek()`` after adding an item to ensure it returns the item but doesn't change the size or remove the item. - ``peek()`` returns the correct item, and ``size()`` remains the same. * - Error Handling (Edge Case) - ``dequeue()``, ``peek()`` - Try to ``dequeue()`` or ``peek()`` an already empty queue. - Both methods return the "Queue is empty" or equivalent error message. --- factorial Demonstration Program To demonstrate understanding of testing, I'll create a simple function to calculate the factorial of a number, along with a complete test suite for it using Python's **unittest**. The Simple Program: Factorial Calculator .. code-block:: python def factorial(n): """ Calculates the factorial of a non-negative integer n (n!). Raises a ValueError for negative numbers or non-integers. """ # Type and Value Guardrails if not isinstance(n, int) or n < 0: raise ValueError("Factorial is only defined for non-negative integers.") # Base Case: 0! = 1 if n == 0: return 1 # Iterative Calculation result = 1 for i in range(1, n + 1): result *= i return result The Test Suite for Factorial Calculator This test suite covers the base case, positive integers, and the required error handling. .. code-block:: python import unittest # Assume the factorial function is imported or defined above class TestFactorial(unittest.TestCase): """ Test suite for the factorial function. """ def test_base_case_zero(self): """ Test the factorial of 0, which should be 1. """ # Arrange, Act, Assert (AAA) self.assertEqual(factorial(0), 1, "0! should be 1") def test_positive_integers(self): """ Test common positive integer factorials (e.g., 1!, 5!). """ # 1! = 1 self.assertEqual(factorial(1), 1) # 5! = 120 (5*4*3*2*1) self.assertEqual(factorial(5), 120) # 7! = 5040 self.assertEqual(factorial(7), 5040) def test_large_integer(self): """ Test a larger number to ensure calculation scale is correct. 10! = 3,628,800 """ self.assertEqual(factorial(10), 3628800) def test_negative_input(self): """ Test that calling with a negative number raises a ValueError. """ # assertRaises checks if the expected exception is raised with self.assertRaises(ValueError): factorial(-1) with self.assertRaises(ValueError): factorial(-5) def test_non_integer_input(self): """ Test that calling with non-integer types (float, string) raises a ValueError. """ with self.assertRaises(ValueError): factorial(4.5) with self.assertRaises(ValueError): factorial("a string") with self.assertRaises(ValueError): factorial(None) # To run the tests, you would typically use: # if __name__ == '__main__': # unittest.main()