diff --git a/solutions/fibonacci.py b/solutions/fibonacci.py new file mode 100644 index 000000000..2ba05dce9 --- /dev/null +++ b/solutions/fibonacci.py @@ -0,0 +1,58 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +""" +A module for generating Fibonacci sequences. + +Module contents: +- generate_fibonacci: Generates Fibonacci sequence up to n terms. + +The Fibonacci sequence is a series of numbers where each number is the sum of the two +preceding ones, starting with 0 and 1. + +Author: Fahed Daibes +Created: 12-Jan-2025 +""" + + +def generate_fibonacci(n: int) -> list: + """ + Generates the first n terms of the Fibonacci sequence. + + Parameters: + - n (int): The number of terms to generate. + + Returns: + - list: A list containing the first n terms of the Fibonacci sequence. + + Raises: + - AssertionError: If the input is not a positive integer. + + Examples: + >>> generate_fibonacci(0) + [] + + >>> generate_fibonacci(1) + [0] + + >>> generate_fibonacci(5) + [0, 1, 1, 2, 3] + + >>> generate_fibonacci("five") + Traceback (most recent call last): + ... + AssertionError: Input must be a non-negative integer. + """ + # Defensive check + assert isinstance(n, int) and n >= 0, "Input must be a non-negative integer." + + if n == 0: + return [] + if n == 1: + return [0] + + sequence = [0, 1] + for _ in range(2, n): + sequence.append(sequence[-1] + sequence[-2]) + + return sequence diff --git a/solutions/tests/test_fibonacci.py b/solutions/tests/test_fibonacci.py new file mode 100644 index 000000000..7337cabc9 --- /dev/null +++ b/solutions/tests/test_fibonacci.py @@ -0,0 +1,80 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +""" +test_fibonacci.py + +This module contains unit tests for the `generate_fibonacci` function, which generates +the Fibonacci sequence up to a given number of terms. + +Author: Fahed Daibes +Date: Jan 12 2025 +Group: ET6-foundations-group-16 + +Tests: +- Valid inputs for various sequence lengths. +- Edge cases, such as n=0 and n=1. +- Invalid inputs, such as negative numbers and non-integer types. +""" + +import unittest + +from solutions.fibonacci import generate_fibonacci + + +def assert_fibonacci(expected, n): + """ + Custom assertion function to compare the result of generate_fibonacci with the expected value. + + Parameters: + - expected (list): The expected Fibonacci sequence. + - n (int): The input number of terms. + + Raises: + - AssertionError: If the result of generate_fibonacci does not match the expected value. + """ + result = generate_fibonacci(n) + assert result == expected, f"Expected {expected} for {n}, but got {result}." + + +class TestFibonacci(unittest.TestCase): + """ + This test class contains unit tests for the `generate_fibonacci` function. + + Each test uses only one assertion with the custom `assert_fibonacci` function. + """ + + def test_zero_terms(self): + """Test case for zero terms.""" + assert_fibonacci([], 0) + + def test_one_term(self): + """Test case for one term.""" + assert_fibonacci([0], 1) + + def test_five_terms(self): + """Test case for five terms.""" + assert_fibonacci([0, 1, 1, 2, 3], 5) + + def test_large_sequence(self): + """Test case for a larger sequence.""" + assert_fibonacci([0, 1, 1, 2, 3, 5, 8, 13, 21, 34], 10) + + def test_negative_input(self): + """Test case for negative input.""" + with self.assertRaises(AssertionError): + generate_fibonacci(-3) + + def test_invalid_string(self): + """Test case for an invalid string input.""" + with self.assertRaises(AssertionError): + generate_fibonacci("ten") + + def test_invalid_float(self): + """Test case for an invalid float input.""" + with self.assertRaises(AssertionError): + generate_fibonacci(3.5) + + +if __name__ == "__main__": + unittest.main()