From c2acb43b8e7947a57bc8858431d0bc7d4d7a7896 Mon Sep 17 00:00:00 2001 From: AnaiMurillo Date: Sat, 28 Dec 2024 19:09:59 -0500 Subject: [PATCH 1/8] feat: create basic calculator folder to start solving challenge #14 --- solutions/basic_calculator/main.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 solutions/basic_calculator/main.py diff --git a/solutions/basic_calculator/main.py b/solutions/basic_calculator/main.py new file mode 100644 index 000000000..e69de29bb From ae216388a8a5841a7dc8a41ac55c4b6c94c31f94 Mon Sep 17 00:00:00 2001 From: AnaiMurillo Date: Sun, 29 Dec 2024 16:38:08 -0500 Subject: [PATCH 2/8] "add solution for performing basic arithmetic operations" --- solutions/basic_calculator/main.py | 70 ++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/solutions/basic_calculator/main.py b/solutions/basic_calculator/main.py index e69de29bb..8403bc92a 100644 --- a/solutions/basic_calculator/main.py +++ b/solutions/basic_calculator/main.py @@ -0,0 +1,70 @@ + + +""" +A module for performing basic arithmetic operations: addition, subtraction, +multiplication, and division. + +Module contents: + - calculate: Performs the specified arithmetic operation on two numbers + +Created on 28/12/2024 +Author: Ana Isabel Murillo +""" + +def calculate(operation: str, num1: float, num2: float) -> float: + """Performs the specified arithmetic operation on two numbers. + + Parameters: + operation: str, the operation to perform ('add', 'subtract', 'multiply', 'divide') + num1: float, the first number + num2: float, the second number + + Returns -> float: the result of the arithmetic operation + + Raises: + ValueError: if the operation is invalid or division by zero occurs + + Examples: + >>> calculate('add', 5, 3) + 8.0 + >>> calculate('subtract', 10, 4) + 6.0 + >>> calculate('multiply', 7, 3) + 21.0 + >>> calculate('divide', 9, 3) + 3.0 + >>> calculate('divide', 5, 0) + Traceback (most recent call last): + ... + ValueError: Cannot divide by zero. + """ + if operation == 'add': + return num1 + num2 + elif operation == 'subtract': + return num1 - num2 + elif operation == 'multiply': + return num1 * num2 + elif operation == 'divide': + if num2 == 0: + raise ValueError("Cannot divide by zero.") + return num1 / num2 + else: + raise ValueError(f"Invalid operation '{operation}'. Valid operations are: add, subtract, multiply, divide.") + +if __name__ == "__main__": + print("Welcome to the Basic Calculator!") + print("Available operations: add, subtract, multiply, divide") + + while True: + try: + operation = input("Enter the operation: ").strip().lower() + num1 = float(input("Enter the first number: ")) + num2 = float(input("Enter the second number: ")) + + result = calculate(operation, num1, num2) + print(f"The result of {operation} operation is: {result}") + break # Exit the loop if the operation is successful + + except ValueError as e: + print(f"Error: {e}") + print("Let's try again!") From 739f957bfe070dd8eac7c951b94860d41d6a36d8 Mon Sep 17 00:00:00 2001 From: AnaiMurillo Date: Wed, 1 Jan 2025 17:43:57 -0500 Subject: [PATCH 3/8] add the test for solution basic calculator --- __init__.py | 0 requirements.txt | Bin 0 -> 28 bytes solutions/__init__.py | 0 solutions/basic_calculator/__init__.py | 0 solutions/tests/__init__.py | 0 solutions/tests/test_basic_calculator.py | 54 +++++++++++++++++++++++ 6 files changed, 54 insertions(+) create mode 100644 __init__.py create mode 100644 requirements.txt create mode 100644 solutions/__init__.py create mode 100644 solutions/basic_calculator/__init__.py create mode 100644 solutions/tests/__init__.py create mode 100644 solutions/tests/test_basic_calculator.py diff --git a/__init__.py b/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..38743267b60f34ea8c94d5c9dd1e4f27b011cfb5 GIT binary patch literal 28 ecmezWuZW?PAq@y^fzW_KkHG?nO&E9?xEKI%6a_i} literal 0 HcmV?d00001 diff --git a/solutions/__init__.py b/solutions/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/solutions/basic_calculator/__init__.py b/solutions/basic_calculator/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/solutions/tests/__init__.py b/solutions/tests/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/solutions/tests/test_basic_calculator.py b/solutions/tests/test_basic_calculator.py new file mode 100644 index 000000000..58550519b --- /dev/null +++ b/solutions/tests/test_basic_calculator.py @@ -0,0 +1,54 @@ +""" +Test module for basic calculator. + +Test categories: + - Standard cases: addition, subtraction, multiplication, and division + - Edge cases: division by zero, invalid operations + - Defensive tests: ensure proper exceptions are raised for invalid inputs + +Created on 2024-12-29 +Author: Ana Isabel Murillo +""" + +from solutions.basic_calculator.main import calculate +import unittest + + +class TestCalculate(unittest.TestCase): + """Test suite for the calculate function.""" + + def test_addition(self): + """It should correctly add two numbers.""" + self.assertEqual(calculate('add', 5, 3), 8.0) + self.assertEqual(calculate('add', -5, -3), -8.0) + self.assertEqual(calculate('add', 0, 5), 5.0) + + def test_subtraction(self): + """It should correctly subtract the second number from the first.""" + self.assertEqual(calculate('subtract', 10, 4), 6.0) + self.assertEqual(calculate('subtract', -5, -5), 0.0) + self.assertEqual(calculate('subtract', 0, 5), -5.0) + + def test_multiplication(self): + """It should correctly multiply two numbers.""" + self.assertEqual(calculate('multiply', 7, 3), 21.0) + self.assertEqual(calculate('multiply', -2, 3), -6.0) + self.assertEqual(calculate('multiply', 0, 10), 0.0) + + def test_division(self): + """It should correctly divide the first number by the second.""" + self.assertEqual(calculate('divide', 9, 3), 3.0) + self.assertEqual(calculate('divide', -6, 3), -2.0) + self.assertAlmostEqual(calculate('divide', 7, 2), 3.5) + + def test_division_by_zero(self): + """It should raise a ValueError when attempting to divide by zero.""" + with self.assertRaises(ValueError) as context: + calculate('divide', 5, 0) + self.assertEqual(str(context.exception), "Cannot divide by zero.") + + def test_invalid_operation(self): + """It should raise a ValueError for an invalid operation.""" + with self.assertRaises(ValueError) as context: + calculate('invalid_op', 5, 3) + self.assertIn("Invalid operation", str(context.exception)) From 286862566027a5804ba8355e08ef770082c143ac Mon Sep 17 00:00:00 2001 From: AnaiMurillo Date: Wed, 1 Jan 2025 17:55:55 -0500 Subject: [PATCH 4/8] remove manual test --- solutions/basic_calculator/main.py | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/solutions/basic_calculator/main.py b/solutions/basic_calculator/main.py index 8403bc92a..7f9aacaec 100644 --- a/solutions/basic_calculator/main.py +++ b/solutions/basic_calculator/main.py @@ -50,21 +50,3 @@ def calculate(operation: str, num1: float, num2: float) -> float: return num1 / num2 else: raise ValueError(f"Invalid operation '{operation}'. Valid operations are: add, subtract, multiply, divide.") - -if __name__ == "__main__": - print("Welcome to the Basic Calculator!") - print("Available operations: add, subtract, multiply, divide") - - while True: - try: - operation = input("Enter the operation: ").strip().lower() - num1 = float(input("Enter the first number: ")) - num2 = float(input("Enter the second number: ")) - - result = calculate(operation, num1, num2) - print(f"The result of {operation} operation is: {result}") - break # Exit the loop if the operation is successful - - except ValueError as e: - print(f"Error: {e}") - print("Let's try again!") From f88df2316684d1772400681c1ab28a415dd4ad43 Mon Sep 17 00:00:00 2001 From: RamonColmenares Date: Wed, 1 Jan 2025 18:07:38 -0500 Subject: [PATCH 5/8] fix issues with ruff linter --- solutions/basic_calculator/main.py | 19 +++++++++------ solutions/tests/test_basic_calculator.py | 31 ++++++++++++------------ 2 files changed, 27 insertions(+), 23 deletions(-) diff --git a/solutions/basic_calculator/main.py b/solutions/basic_calculator/main.py index 7f9aacaec..39d6bd597 100644 --- a/solutions/basic_calculator/main.py +++ b/solutions/basic_calculator/main.py @@ -1,5 +1,3 @@ - - """ A module for performing basic arithmetic operations: addition, subtraction, multiplication, and division. @@ -11,11 +9,13 @@ Author: Ana Isabel Murillo """ + def calculate(operation: str, num1: float, num2: float) -> float: """Performs the specified arithmetic operation on two numbers. Parameters: - operation: str, the operation to perform ('add', 'subtract', 'multiply', 'divide') + operation: str, the operation to perform + ('add', 'subtract', 'multiply', 'divide') num1: float, the first number num2: float, the second number @@ -38,15 +38,18 @@ def calculate(operation: str, num1: float, num2: float) -> float: ... ValueError: Cannot divide by zero. """ - if operation == 'add': + if operation == "add": return num1 + num2 - elif operation == 'subtract': + elif operation == "subtract": return num1 - num2 - elif operation == 'multiply': + elif operation == "multiply": return num1 * num2 - elif operation == 'divide': + elif operation == "divide": if num2 == 0: raise ValueError("Cannot divide by zero.") return num1 / num2 else: - raise ValueError(f"Invalid operation '{operation}'. Valid operations are: add, subtract, multiply, divide.") + raise ValueError( + f"Invalid operation '{operation}'. Valid operations are: " + "add, subtract, multiply, divide." + ) diff --git a/solutions/tests/test_basic_calculator.py b/solutions/tests/test_basic_calculator.py index 58550519b..1e9d80b76 100644 --- a/solutions/tests/test_basic_calculator.py +++ b/solutions/tests/test_basic_calculator.py @@ -10,45 +10,46 @@ Author: Ana Isabel Murillo """ -from solutions.basic_calculator.main import calculate import unittest +from solutions.basic_calculator.main import calculate + class TestCalculate(unittest.TestCase): """Test suite for the calculate function.""" def test_addition(self): """It should correctly add two numbers.""" - self.assertEqual(calculate('add', 5, 3), 8.0) - self.assertEqual(calculate('add', -5, -3), -8.0) - self.assertEqual(calculate('add', 0, 5), 5.0) + self.assertEqual(calculate("add", 5, 3), 8.0) + self.assertEqual(calculate("add", -5, -3), -8.0) + self.assertEqual(calculate("add", 0, 5), 5.0) def test_subtraction(self): """It should correctly subtract the second number from the first.""" - self.assertEqual(calculate('subtract', 10, 4), 6.0) - self.assertEqual(calculate('subtract', -5, -5), 0.0) - self.assertEqual(calculate('subtract', 0, 5), -5.0) + self.assertEqual(calculate("subtract", 10, 4), 6.0) + self.assertEqual(calculate("subtract", -5, -5), 0.0) + self.assertEqual(calculate("subtract", 0, 5), -5.0) def test_multiplication(self): """It should correctly multiply two numbers.""" - self.assertEqual(calculate('multiply', 7, 3), 21.0) - self.assertEqual(calculate('multiply', -2, 3), -6.0) - self.assertEqual(calculate('multiply', 0, 10), 0.0) + self.assertEqual(calculate("multiply", 7, 3), 21.0) + self.assertEqual(calculate("multiply", -2, 3), -6.0) + self.assertEqual(calculate("multiply", 0, 10), 0.0) def test_division(self): """It should correctly divide the first number by the second.""" - self.assertEqual(calculate('divide', 9, 3), 3.0) - self.assertEqual(calculate('divide', -6, 3), -2.0) - self.assertAlmostEqual(calculate('divide', 7, 2), 3.5) + self.assertEqual(calculate("divide", 9, 3), 3.0) + self.assertEqual(calculate("divide", -6, 3), -2.0) + self.assertAlmostEqual(calculate("divide", 7, 2), 3.5) def test_division_by_zero(self): """It should raise a ValueError when attempting to divide by zero.""" with self.assertRaises(ValueError) as context: - calculate('divide', 5, 0) + calculate("divide", 5, 0) self.assertEqual(str(context.exception), "Cannot divide by zero.") def test_invalid_operation(self): """It should raise a ValueError for an invalid operation.""" with self.assertRaises(ValueError) as context: - calculate('invalid_op', 5, 3) + calculate("invalid_op", 5, 3) self.assertIn("Invalid operation", str(context.exception)) From 7b91346bb080f931c07d0f17ea05ed80b19e54c6 Mon Sep 17 00:00:00 2001 From: AnaiMurillo Date: Sat, 11 Jan 2025 20:21:45 -0500 Subject: [PATCH 6/8] Change file name --- .../{main.py => basic_calculator.py} | 0 solutions/tests/test_basic_calculator.py | 30 +++++++++---------- 2 files changed, 15 insertions(+), 15 deletions(-) rename solutions/basic_calculator/{main.py => basic_calculator.py} (100%) diff --git a/solutions/basic_calculator/main.py b/solutions/basic_calculator/basic_calculator.py similarity index 100% rename from solutions/basic_calculator/main.py rename to solutions/basic_calculator/basic_calculator.py diff --git a/solutions/tests/test_basic_calculator.py b/solutions/tests/test_basic_calculator.py index 58550519b..df5fcb798 100644 --- a/solutions/tests/test_basic_calculator.py +++ b/solutions/tests/test_basic_calculator.py @@ -10,7 +10,7 @@ Author: Ana Isabel Murillo """ -from solutions.basic_calculator.main import calculate +from solutions.basic_calculator.basic_calculator import calculate import unittest @@ -19,36 +19,36 @@ class TestCalculate(unittest.TestCase): def test_addition(self): """It should correctly add two numbers.""" - self.assertEqual(calculate('add', 5, 3), 8.0) - self.assertEqual(calculate('add', -5, -3), -8.0) - self.assertEqual(calculate('add', 0, 5), 5.0) + self.assertEqual(calculate("add", 5, 3), 8.0) + self.assertEqual(calculate("add", -5, -3), -8.0) + self.assertEqual(calculate("add", 0, 5), 5.0) def test_subtraction(self): """It should correctly subtract the second number from the first.""" - self.assertEqual(calculate('subtract', 10, 4), 6.0) - self.assertEqual(calculate('subtract', -5, -5), 0.0) - self.assertEqual(calculate('subtract', 0, 5), -5.0) + self.assertEqual(calculate("subtract", 10, 4), 6.0) + self.assertEqual(calculate("subtract", -5, -5), 0.0) + self.assertEqual(calculate("subtract", 0, 5), -5.0) def test_multiplication(self): """It should correctly multiply two numbers.""" - self.assertEqual(calculate('multiply', 7, 3), 21.0) - self.assertEqual(calculate('multiply', -2, 3), -6.0) - self.assertEqual(calculate('multiply', 0, 10), 0.0) + self.assertEqual(calculate("multiply", 7, 3), 21.0) + self.assertEqual(calculate("multiply", -2, 3), -6.0) + self.assertEqual(calculate("multiply", 0, 10), 0.0) def test_division(self): """It should correctly divide the first number by the second.""" - self.assertEqual(calculate('divide', 9, 3), 3.0) - self.assertEqual(calculate('divide', -6, 3), -2.0) - self.assertAlmostEqual(calculate('divide', 7, 2), 3.5) + self.assertEqual(calculate("divide", 9, 3), 3.0) + self.assertEqual(calculate("divide", -6, 3), -2.0) + self.assertAlmostEqual(calculate("divide", 7, 2), 3.5) def test_division_by_zero(self): """It should raise a ValueError when attempting to divide by zero.""" with self.assertRaises(ValueError) as context: - calculate('divide', 5, 0) + calculate("divide", 5, 0) self.assertEqual(str(context.exception), "Cannot divide by zero.") def test_invalid_operation(self): """It should raise a ValueError for an invalid operation.""" with self.assertRaises(ValueError) as context: - calculate('invalid_op', 5, 3) + calculate("invalid_op", 5, 3) self.assertIn("Invalid operation", str(context.exception)) From 3352cdc417e75761739b73619e96980f5601ff0a Mon Sep 17 00:00:00 2001 From: AnaiMurillo Date: Sat, 11 Jan 2025 21:34:26 -0500 Subject: [PATCH 7/8] Give each test only one assertion --- solutions/tests/test_basic_calculator.py | 40 +++++++++++++++++++----- 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/solutions/tests/test_basic_calculator.py b/solutions/tests/test_basic_calculator.py index 70a8c4195..d9b961c2e 100644 --- a/solutions/tests/test_basic_calculator.py +++ b/solutions/tests/test_basic_calculator.py @@ -18,28 +18,52 @@ class TestCalculate(unittest.TestCase): """Test suite for the calculate function.""" - def test_addition(self): - """It should correctly add two numbers.""" + def test_addition_positive_numbers(self): + """It should correctly add two positive numbers.""" self.assertEqual(calculate("add", 5, 3), 8.0) + + def test_addition_negative_numbers(self): + """It should correctly add two negative numbers.""" self.assertEqual(calculate("add", -5, -3), -8.0) + + def test_addition_zero(self): + """It should correctly add zero to a number.""" self.assertEqual(calculate("add", 0, 5), 5.0) - def test_subtraction(self): - """It should correctly subtract the second number from the first.""" + def test_subtraction_positive_numbers(self): + """It should correctly subtract two positive numbers.""" self.assertEqual(calculate("subtract", 10, 4), 6.0) + + def test_subtraction_negative_numbers(self): + """It should correctly subtract two negative numbers.""" self.assertEqual(calculate("subtract", -5, -5), 0.0) + + def test_subtraction_zero(self): + """It should correctly subtract a number from zero.""" self.assertEqual(calculate("subtract", 0, 5), -5.0) - def test_multiplication(self): - """It should correctly multiply two numbers.""" + def test_multiplication_positive_numbers(self): + """It should correctly multiply two positive numbers.""" self.assertEqual(calculate("multiply", 7, 3), 21.0) + + def test_multiplication_negative_numbers(self): + """It should correctly multiply a negative and a positive number.""" self.assertEqual(calculate("multiply", -2, 3), -6.0) + + def test_multiplication_with_zero(self): + """It should return zero when multiplying by zero.""" self.assertEqual(calculate("multiply", 0, 10), 0.0) - def test_division(self): - """It should correctly divide the first number by the second.""" + def test_division_positive_numbers(self): + """It should correctly divide two positive numbers.""" self.assertEqual(calculate("divide", 9, 3), 3.0) + + def test_division_negative_numbers(self): + """It should correctly divide a negative and a positive number.""" self.assertEqual(calculate("divide", -6, 3), -2.0) + + def test_division_result_with_float(self): + """It should correctly handle division resulting in a float.""" self.assertAlmostEqual(calculate("divide", 7, 2), 3.5) def test_division_by_zero(self): From 009d8568bfba8a2eb7353b6781ce6f2f95680c39 Mon Sep 17 00:00:00 2001 From: AnaiMurillo Date: Sun, 12 Jan 2025 14:28:01 -0500 Subject: [PATCH 8/8] change file name --- .../basic_calculator/{basic_calculator.py => calculate.py} | 0 solutions/tests/test_basic_calculator.py | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename solutions/basic_calculator/{basic_calculator.py => calculate.py} (100%) diff --git a/solutions/basic_calculator/basic_calculator.py b/solutions/basic_calculator/calculate.py similarity index 100% rename from solutions/basic_calculator/basic_calculator.py rename to solutions/basic_calculator/calculate.py diff --git a/solutions/tests/test_basic_calculator.py b/solutions/tests/test_basic_calculator.py index d9b961c2e..752f63ce1 100644 --- a/solutions/tests/test_basic_calculator.py +++ b/solutions/tests/test_basic_calculator.py @@ -10,7 +10,7 @@ Author: Ana Isabel Murillo """ -from solutions.basic_calculator.basic_calculator import calculate +from solutions.basic_calculator.calculate import calculate import unittest