Skip to content
This repository was archived by the owner on Jun 13, 2025. It is now read-only.

Commit f264d0d

Browse files
Add Tests for PR#1240
1 parent e463004 commit f264d0d

File tree

1 file changed

+283
-0
lines changed

1 file changed

+283
-0
lines changed

api/gen_ai/tests/test_math.py

Lines changed: 283 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,283 @@
1+
import unittest
2+
from datetime import datetime
3+
from unittest import TestCase
4+
5+
from api.gen_ai.math import (
6+
Calculator,
7+
DataProcessor,
8+
StringManipulator,
9+
add,
10+
divide,
11+
factorial,
12+
fibonacci,
13+
is_prime,
14+
merge_dicts,
15+
parse_date,
16+
safe_list_access,
17+
subtract,
18+
)
19+
20+
21+
class BasicArithmeticTests(TestCase):
22+
def test_add(self):
23+
self.assertEqual(add(2, 3), 5)
24+
self.assertEqual(add(-1, 1), 0)
25+
self.assertEqual(add(0, 0), 0)
26+
self.assertEqual(add(2.5, 3.5), 6.0)
27+
28+
def test_subtract(self):
29+
self.assertEqual(subtract(5, 3), 2)
30+
self.assertEqual(subtract(1, 1), 0)
31+
self.assertEqual(subtract(0, 5), -5)
32+
self.assertEqual(subtract(5.5, 2.5), 3.0)
33+
34+
def test_divide(self):
35+
self.assertEqual(divide(6, 3), 2)
36+
self.assertEqual(divide(5, 2), 2.5)
37+
self.assertEqual(divide(0, 5), 0)
38+
self.assertEqual(divide(-6, 3), -2)
39+
40+
def test_divide_by_zero(self):
41+
with self.assertRaises(ValueError) as context:
42+
divide(5, 0)
43+
self.assertEqual(str(context.exception), "Division by zero is not allowed")
44+
45+
46+
class FactorialTests(TestCase):
47+
def test_factorial_zero(self):
48+
self.assertEqual(factorial(0), 1)
49+
50+
def test_factorial_one(self):
51+
self.assertEqual(factorial(1), 1)
52+
53+
def test_factorial_positive(self):
54+
self.assertEqual(factorial(5), 120)
55+
self.assertEqual(factorial(10), 3628800)
56+
57+
def test_factorial_negative(self):
58+
with self.assertRaises(ValueError) as context:
59+
factorial(-1)
60+
self.assertEqual(str(context.exception), "Negative numbers do not have factorials")
61+
62+
63+
class PrimeTests(TestCase):
64+
def test_is_prime_negative_and_zero(self):
65+
self.assertFalse(is_prime(-5))
66+
self.assertFalse(is_prime(0))
67+
68+
def test_is_prime_one(self):
69+
self.assertFalse(is_prime(1))
70+
71+
def test_is_prime_two_and_three(self):
72+
self.assertTrue(is_prime(2))
73+
self.assertTrue(is_prime(3))
74+
75+
def test_is_prime_regular_cases(self):
76+
self.assertTrue(is_prime(5))
77+
self.assertTrue(is_prime(7))
78+
self.assertTrue(is_prime(11))
79+
self.assertTrue(is_prime(13))
80+
self.assertTrue(is_prime(17))
81+
self.assertTrue(is_prime(19))
82+
self.assertTrue(is_prime(23))
83+
84+
self.assertFalse(is_prime(4))
85+
self.assertFalse(is_prime(6))
86+
self.assertFalse(is_prime(8))
87+
self.assertFalse(is_prime(9))
88+
self.assertFalse(is_prime(10))
89+
90+
def test_is_prime_larger_numbers(self):
91+
self.assertTrue(is_prime(97))
92+
self.assertFalse(is_prime(100))
93+
94+
95+
class FibonacciTests(TestCase):
96+
def test_fibonacci_zero(self):
97+
self.assertEqual(fibonacci(0), 0)
98+
99+
def test_fibonacci_one(self):
100+
self.assertEqual(fibonacci(1), 1)
101+
102+
def test_fibonacci_sequence(self):
103+
expected_sequence = [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
104+
for n, expected in enumerate(expected_sequence):
105+
self.assertEqual(fibonacci(n), expected)
106+
107+
def test_fibonacci_negative(self):
108+
with self.assertRaises(ValueError) as context:
109+
fibonacci(-1)
110+
self.assertEqual(str(context.exception), "n must be a non-negative integer")
111+
112+
113+
class CalculatorTests(TestCase):
114+
def setUp(self):
115+
self.calculator = Calculator()
116+
117+
def test_add(self):
118+
self.assertEqual(self.calculator.add(2, 3), 5)
119+
self.assertEqual(self.calculator.add(-1, 1), 0)
120+
121+
def test_subtract(self):
122+
self.assertEqual(self.calculator.subtract(5, 3), 2)
123+
self.assertEqual(self.calculator.subtract(1, 1), 0)
124+
125+
def test_multiply(self):
126+
self.assertEqual(self.calculator.multiply(2, 3), 6)
127+
self.assertEqual(self.calculator.multiply(5, 0), 0)
128+
129+
def test_divide(self):
130+
self.assertEqual(self.calculator.divide(6, 3), 2)
131+
self.assertEqual(self.calculator.divide(5, 2), 2.5)
132+
133+
def test_divide_by_zero(self):
134+
with self.assertRaises(ValueError) as context:
135+
self.calculator.divide(5, 0)
136+
self.assertEqual(str(context.exception), "Cannot divide by zero")
137+
138+
def test_memory_operations(self):
139+
# Initial memory is 0
140+
self.assertEqual(self.calculator.memory, 0)
141+
142+
# Store value
143+
self.calculator.store(42)
144+
self.assertEqual(self.calculator.memory, 42)
145+
146+
# Recall value
147+
self.assertEqual(self.calculator.recall(), 42)
148+
149+
# Store new value
150+
self.calculator.store(-10)
151+
self.assertEqual(self.calculator.recall(), -10)
152+
153+
154+
class StringManipulatorTests(TestCase):
155+
def test_reverse_string(self):
156+
self.assertEqual(StringManipulator.reverse_string("hello"), "olleh")
157+
self.assertEqual(StringManipulator.reverse_string(""), "")
158+
self.assertEqual(StringManipulator.reverse_string("a"), "a")
159+
self.assertEqual(StringManipulator.reverse_string("12345"), "54321")
160+
161+
def test_is_palindrome(self):
162+
# Simple cases
163+
self.assertTrue(StringManipulator.is_palindrome("racecar"))
164+
self.assertTrue(StringManipulator.is_palindrome("madam"))
165+
self.assertTrue(StringManipulator.is_palindrome(""))
166+
self.assertTrue(StringManipulator.is_palindrome("a"))
167+
self.assertFalse(StringManipulator.is_palindrome("hello"))
168+
169+
# Case insensitivity
170+
self.assertTrue(StringManipulator.is_palindrome("Madam"))
171+
self.assertTrue(StringManipulator.is_palindrome("RaceCar"))
172+
173+
# Ignoring non-alphanumeric characters
174+
self.assertTrue(StringManipulator.is_palindrome("A man, a plan, a canal: Panama"))
175+
self.assertTrue(StringManipulator.is_palindrome("No 'x' in Nixon"))
176+
177+
178+
class DataProcessorTests(TestCase):
179+
def test_constructor_empty_data(self):
180+
with self.assertRaises(ValueError) as context:
181+
DataProcessor([])
182+
self.assertEqual(str(context.exception), "Data list cannot be empty")
183+
184+
def test_get_mean(self):
185+
processor = DataProcessor([1, 2, 3, 4, 5])
186+
self.assertEqual(processor.get_mean(), 3)
187+
188+
processor = DataProcessor([0, 0, 0])
189+
self.assertEqual(processor.get_mean(), 0)
190+
191+
processor = DataProcessor([1.5, 2.5, 3.5])
192+
self.assertEqual(processor.get_mean(), 2.5)
193+
194+
def test_get_variance(self):
195+
processor = DataProcessor([1, 2, 3, 4, 5])
196+
self.assertEqual(processor.get_variance(), 2.5)
197+
198+
processor = DataProcessor([0, 0, 0])
199+
self.assertEqual(processor.get_variance(), 0)
200+
201+
def test_get_variance_single_element(self):
202+
processor = DataProcessor([42])
203+
with self.assertRaises(ValueError) as context:
204+
processor.get_variance()
205+
self.assertEqual(str(context.exception), "At least two data points are required to compute variance")
206+
207+
def test_normalize(self):
208+
processor = DataProcessor([1, 2, 3, 4, 5])
209+
expected = [-1.2649110640673518, -0.6324555320336759, 0, 0.6324555320336759, 1.2649110640673518]
210+
normalized = processor.normalize()
211+
self.assertEqual(len(normalized), 5)
212+
for actual, expected_value in zip(normalized, expected):
213+
self.assertAlmostEqual(actual, expected_value)
214+
215+
def test_normalize_zero_std_dev(self):
216+
processor = DataProcessor([2, 2, 2])
217+
with self.assertRaises(ValueError) as context:
218+
processor.normalize()
219+
self.assertEqual(str(context.exception), "Standard deviation is zero, cannot normalize.")
220+
221+
222+
class DateParsingTests(TestCase):
223+
def test_parse_date_default_format(self):
224+
date = parse_date("2023-01-15")
225+
self.assertEqual(date.year, 2023)
226+
self.assertEqual(date.month, 1)
227+
self.assertEqual(date.day, 15)
228+
229+
def test_parse_date_custom_format(self):
230+
date = parse_date("15/01/2023", fmt="%d/%m/%Y")
231+
self.assertEqual(date.year, 2023)
232+
self.assertEqual(date.month, 1)
233+
self.assertEqual(date.day, 15)
234+
235+
def test_parse_date_invalid_format(self):
236+
with self.assertRaises(ValueError) as context:
237+
parse_date("15-01-2023")
238+
self.assertEqual(str(context.exception), "Incorrect date format, should be YYYY-MM-DD")
239+
240+
241+
class SafeListAccessTests(TestCase):
242+
def test_safe_list_access_valid_index(self):
243+
lst = [10, 20, 30, 40, 50]
244+
self.assertEqual(safe_list_access(lst, 2), 30)
245+
246+
def test_safe_list_access_invalid_index(self):
247+
lst = [10, 20, 30]
248+
self.assertIsNone(safe_list_access(lst, 10))
249+
250+
def test_safe_list_access_custom_default(self):
251+
lst = [10, 20, 30]
252+
self.assertEqual(safe_list_access(lst, 10, default="Not found"), "Not found")
253+
254+
255+
class MergeDictsTests(TestCase):
256+
def test_merge_dicts_simple(self):
257+
dict1 = {"a": 1, "b": 2}
258+
dict2 = {"c": 3, "d": 4}
259+
result = merge_dicts(dict1, dict2)
260+
self.assertEqual(result, {"a": 1, "b": 2, "c": 3, "d": 4})
261+
262+
def test_merge_dicts_with_overlap(self):
263+
dict1 = {"a": 1, "b": 2}
264+
dict2 = {"b": 3, "c": 4}
265+
result = merge_dicts(dict1, dict2)
266+
self.assertEqual(result, {"a": 1, "b": 3, "c": 4})
267+
268+
def test_merge_dicts_nested(self):
269+
dict1 = {"a": 1, "b": {"x": 1, "y": 2}}
270+
dict2 = {"b": {"y": 3, "z": 4}, "c": 5}
271+
result = merge_dicts(dict1, dict2)
272+
self.assertEqual(result, {"a": 1, "b": {"x": 1, "y": 3, "z": 4}, "c": 5})
273+
274+
def test_original_dicts_unchanged(self):
275+
dict1 = {"a": 1, "b": 2}
276+
dict2 = {"c": 3, "d": 4}
277+
original_dict1 = dict1.copy()
278+
original_dict2 = dict2.copy()
279+
280+
merge_dicts(dict1, dict2)
281+
282+
self.assertEqual(dict1, original_dict1)
283+
self.assertEqual(dict2, original_dict2)

0 commit comments

Comments
 (0)