From e6604a97c0ed3db43dd8294c472f5adca7223bda Mon Sep 17 00:00:00 2001 From: enias Date: Mon, 25 Aug 2025 01:14:49 -0400 Subject: [PATCH] Fix: Create fibonacci function (#8) --- src/utils/math_functions.py | 64 +++++++++++++++++++++++ tests/test_math_functions.py | 80 ++++++++++++++++++++++++++++ tests/test_test_math_functions.py | 86 +++++++++++++++++++++++++++++++ 3 files changed, 230 insertions(+) create mode 100644 src/utils/math_functions.py create mode 100644 tests/test_math_functions.py create mode 100644 tests/test_test_math_functions.py diff --git a/src/utils/math_functions.py b/src/utils/math_functions.py new file mode 100644 index 0000000..b015b66 --- /dev/null +++ b/src/utils/math_functions.py @@ -0,0 +1,64 @@ +```python +def fibonacci(n): + """ + Generate a list of Fibonacci numbers up to the nth term. + + The Fibonacci sequence is a series of numbers where each number is the sum + of the two preceding ones, starting from 0 and 1. + + Parameters: + ----------- + n : int + The number of Fibonacci terms to generate. Must be a non-negative integer. + + Returns: + -------- + list + A list containing the first n Fibonacci numbers. Returns an empty list + if n is 0, [0] if n is 1, [0, 1] if n is 2, etc. + + Raises: + ------- + TypeError + If n is not an integer. + ValueError + If n is a negative integer. + + Examples: + --------- + >>> fibonacci(0) + [] + + >>> fibonacci(1) + [0] + + >>> fibonacci(5) + [0, 1, 1, 2, 3] + + >>> fibonacci(10) + [0, 1, 1, 2, 3, 5, 8, 13, 21, 34] + + Notes: + ------ + - Input validation: n must be a non-negative integer + - For n=0: returns empty list + - For n=1: returns [0] + - For n>=2: returns [0, 1, ...] with n terms + """ + if not isinstance(n, int): + raise TypeError("n must be an integer") + if n < 0: + raise ValueError("n must be a non-negative integer") + + if n == 0: + return [] + elif n == 1: + return [0] + + fib_sequence = [0, 1] + for i in range(2, n): + next_term = fib_sequence[i-1] + fib_sequence[i-2] + fib_sequence.append(next_term) + + return fib_sequence +``` \ No newline at end of file diff --git a/tests/test_math_functions.py b/tests/test_math_functions.py new file mode 100644 index 0000000..17c56fe --- /dev/null +++ b/tests/test_math_functions.py @@ -0,0 +1,80 @@ +```python +import pytest +from your_module import fibonacci # Replace 'your_module' with actual module name + + +class TestFibonacci: + """Test suite for fibonacci function""" + + def test_base_cases(self): + """Test base cases: n=0, n=1, n=2""" + assert fibonacci(0) == [] + assert fibonacci(1) == [0] + assert fibonacci(2) == [0, 1] + + def test_small_positive_numbers(self): + """Test small positive values of n""" + assert fibonacci(3) == [0, 1, 1] + assert fibonacci(4) == [0, 1, 1, 2] + assert fibonacci(5) == [0, 1, 1, 2, 3] + assert fibonacci(6) == [0, 1, 1, 2, 3, 5] + assert fibonacci(7) == [0, 1, 1, 2, 3, 5, 8] + + def test_larger_positive_numbers(self): + """Test larger positive values of n""" + assert fibonacci(10) == [0, 1, 1, 2, 3, 5, 8, 13, 21, 34] + assert len(fibonacci(15)) == 15 + assert fibonacci(15)[-1] == 377 # 15th Fibonacci number + + def test_negative_input(self): + """Test that negative input raises ValueError""" + with pytest.raises(ValueError, match="n must be a non-negative integer"): + fibonacci(-1) + with pytest.raises(ValueError, match="n must be a non-negative integer"): + fibonacci(-10) + + def test_non_integer_input(self): + """Test that non-integer input raises TypeError""" + with pytest.raises(TypeError, match="n must be an integer"): + fibonacci(3.5) + with pytest.raises(TypeError, match="n must be an integer"): + fibonacci("5") + with pytest.raises(TypeError, match="n must be an integer"): + fibonacci([1]) + with pytest.raises(TypeError, match="n must be an integer"): + fibonacci(None) + + def test_zero_input(self): + """Test that n=0 returns empty list""" + result = fibonacci(0) + assert result == [] + assert isinstance(result, list) + + def test_sequence_correctness(self): + """Test that the sequence follows Fibonacci rules""" + # Test that each term is the sum of the two preceding terms + n = 10 + sequence = fibonacci(n) + for i in range(2, n): + assert sequence[i] == sequence[i-1] + sequence[i-2] + + def test_return_type(self): + """Test that the function always returns a list""" + assert isinstance(fibonacci(0), list) + assert isinstance(fibonacci(1), list) + assert isinstance(fibonacci(5), list) + assert isinstance(fibonacci(10), list) + + def test_very_small_n(self): + """Test edge cases with very small n values""" + assert fibonacci(0) == [] + assert fibonacci(1) == [0] + assert fibonacci(2) == [0, 1] + + def test_consistency_across_calls(self): + """Test that multiple calls with same input give same result""" + result1 = fibonacci(5) + result2 = fibonacci(5) + assert result1 == result2 + assert result1 is not result2 # Should return new list each time +``` \ No newline at end of file diff --git a/tests/test_test_math_functions.py b/tests/test_test_math_functions.py new file mode 100644 index 0000000..fc691ae --- /dev/null +++ b/tests/test_test_math_functions.py @@ -0,0 +1,86 @@ +```python +import pytest +from src.utils.math_functions import fibonacci + + +class TestFibonacci: + """Test cases for the fibonacci function.""" + + def test_fibonacci_n_0(self): + """Test fibonacci with n=0 returns [0].""" + result = fibonacci(0) + assert result == [0] + + def test_fibonacci_n_1(self): + """Test fibonacci with n=1 returns [0, 1].""" + result = fibonacci(1) + assert result == [0, 1] + + def test_fibonacci_n_2(self): + """Test fibonacci with n=2 returns [0, 1, 1].""" + result = fibonacci(2) + assert result == [0, 1, 1] + + def test_fibonacci_n_5(self): + """Test fibonacci with n=5 returns correct sequence.""" + result = fibonacci(5) + assert result == [0, 1, 1, 2, 3, 5] + + def test_fibonacci_n_10(self): + """Test fibonacci with n=10 returns correct sequence.""" + result = fibonacci(10) + expected = [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55] + assert result == expected + + def test_fibonacci_large_n(self): + """Test fibonacci with a larger n value.""" + result = fibonacci(15) + expected = [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610] + assert result == expected + + def test_fibonacci_negative_input(self): + """Test fibonacci with negative input raises ValueError.""" + with pytest.raises(ValueError): + fibonacci(-1) + + with pytest.raises(ValueError): + fibonacci(-10) + + def test_fibonacci_non_integer_input(self): + """Test fibonacci with non-integer input raises TypeError.""" + with pytest.raises(TypeError): + fibonacci("5") + + with pytest.raises(TypeError): + fibonacci(5.5) + + with pytest.raises(TypeError): + fibonacci([5]) + + with pytest.raises(TypeError): + fibonacci(None) + + def test_fibonacci_return_type(self): + """Test that fibonacci returns a list.""" + result = fibonacci(5) + assert isinstance(result, list) + + def test_fibonacci_sequence_length(self): + """Test that fibonacci sequence has correct length (n+1).""" + for n in [0, 1, 5, 10]: + result = fibonacci(n) + assert len(result) == n + 1 + + def test_fibonacci_sequence_property(self): + """Test that each element satisfies the Fibonacci recurrence relation.""" + n = 10 + result = fibonacci(n) + + # Check first two elements + assert result[0] == 0 + assert result[1] == 1 + + # Check recurrence relation for remaining elements + for i in range(2, n + 1): + assert result[i] == result[i - 1] + result[i - 2] +``` \ No newline at end of file