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.
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 usespop(0)).
The Test Suite Explanation
Test Case Category |
Methods Covered |
Description of Test |
Expected Outcome |
|---|---|---|---|
Basic Operations |
|
Test adding one item, then removing it. |
|
FIFO Integrity |
|
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) |
|
Test a newly instantiated queue. |
|
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. |
|
|
Check |
|
Error Handling (Edge Case) |
|
Try to |
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
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.
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()