diff --git a/.github/workflows/ci-checks.yml b/.github/workflows/ci-checks.yml index b3d7b0052..7f11e8725 100644 --- a/.github/workflows/ci-checks.yml +++ b/.github/workflows/ci-checks.yml @@ -51,30 +51,33 @@ jobs: run: "pylint solutions tests || echo '::warning title=Pylint Error(s)::Discuss solutions and trade-offs in code review.'" shell: bash - py_tests: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - - name: python version - run: python --version - shell: bash - - - name: Check for test files - id: check_tests - run: | - test_files=$(find ./solutions/tests -type f -name "test_*.py") - if [ -n "$test_files" ]; then - echo "Found test files:" - echo "$test_files" - echo "has_tests=true" >> $GITHUB_OUTPUT - else - echo "No test files found matching pattern ./solutions/tests/test_*.py" - echo "has_tests=false" >> $GITHUB_OUTPUT - fi - shell: bash - - - name: Python - Run Tests - if: steps.check_tests.outputs.has_tests == 'true' - run: python -m unittest - shell: bash + py_tests: + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up Python + run: python --version + shell: bash + + - name: Check for test files + id: check_tests + run: | + test_files=$(find ./solutions/tests -type f -name "test_*.py") + if [ -n "$test_files" ]; then + echo "Found test files:" + echo "$test_files" + echo "has_tests=true" >> $GITHUB_ENV + else + echo "No test files found matching pattern ./solutions/tests/test_*.py" + echo "has_tests=false" >> $GITHUB_ENV + fi + shell: bash + + - name: Python - Run Tests + if: env.has_tests == 'true' + env: + PYTHONPATH: ${{ github.workspace }} + run: python -m unittest discover -s solutions/tests + shell: bash diff --git a/.vscode/settings.json b/.vscode/settings.json index 252022b48..d40e712be 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -122,5 +122,8 @@ "source.fixAll.ruff": "explicit", "source.organizeImports.ruff": "explicit" } - } + }, + "python.testing.unittestArgs": ["-v", "-s", "./solutions", "-p", "test_*.py"], + "python.testing.pytestEnabled": false, + "python.testing.unittestEnabled": true } diff --git a/solutions/multiply.py b/solutions/multiply.py new file mode 100644 index 000000000..d8a224fd9 --- /dev/null +++ b/solutions/multiply.py @@ -0,0 +1,33 @@ +""" +multiply.py + +This module provides a function to multiply two numbers. +""" + + +def multiply(a: float, b: float) -> float: + """ + Multiplies two numbers and returns the result. + + Args: + a (float): The first number. + b (float): The second number. + + Returns: + float: The product of a and b. + + Raises: + TypeError: If the inputs are not numbers. + + Examples: + >>> multiply(2, 3) + 6 + >>> multiply(5.5, 2) + 11.0 + >>> multiply(-4, 3) + -12 + """ + if not isinstance(a, (int, float)) or not isinstance(b, (int, float)): + raise TypeError("Both inputs must be numbers.") + + return a * b diff --git a/solutions/sum_positive_numbers.py b/solutions/sum_positive_numbers.py new file mode 100644 index 000000000..5f4482c28 --- /dev/null +++ b/solutions/sum_positive_numbers.py @@ -0,0 +1,39 @@ +""" +sum_positive_numbers.py + +This module provides a function to sum only the positive numbers in a list. +""" + +from typing import List + + +def sum_positive_numbers(numbers: List[float]) -> float: + """ + Calculate the sum of positive numbers in a given list. + + Args: + numbers (List[float]): A list of floating point or integer numbers. + + Returns: + float: The sum of all positive numbers in the list. If no positive numbers, returns 0. + + Raises: + TypeError: If the input is not a list. + ValueError: If any element in the list is not a number. + + Examples: + >>> sum_positive_numbers([1, -2, 3.5, 0, -1]) + 4.5 + >>> sum_positive_numbers([-10, -20, -30]) + 0 + >>> sum_positive_numbers([5, 10, 15]) + 30 + """ + if not isinstance(numbers, list): + raise TypeError("Input must be a list.") + + for num in numbers: + if not isinstance(num, (int, float)): + raise ValueError("All elements in the list must be numbers.") + + return sum(num for num in numbers if num > 0) diff --git a/solutions/tests/test_multiply.py b/solutions/tests/test_multiply.py new file mode 100644 index 000000000..276e4ede3 --- /dev/null +++ b/solutions/tests/test_multiply.py @@ -0,0 +1,37 @@ +""" +test_multiply.py + +Unit tests for the multiply function. +""" + +import unittest +from solutions.multiply import multiply + + +class TestMultiply(unittest.TestCase): + """Tests for multiply function.""" + + def test_positive_numbers(self): + """Should return the product of two positive numbers.""" + self.assertEqual(multiply(2, 3), 6) + + def test_negative_numbers(self): + """Should return the correct product for negative numbers.""" + self.assertEqual(multiply(-4, 3), -12) + + + def test_zero(self): + """Should return 0 if either number is 0.""" + self.assertEqual(multiply(3, 0), 0) + + def test_floats(self): + """Should correctly multiply floating point numbers.""" + self.assertEqual(multiply(2.5, 2), 5.0) + + def test_invalid_input_type(self): + """Should raise TypeError if inputs are not numbers.""" + with self.assertRaises(TypeError): + multiply("2", 3) + +if __name__ == "__main__": + unittest.main() diff --git a/solutions/tests/test_sum_positive_numbers.py b/solutions/tests/test_sum_positive_numbers.py new file mode 100644 index 000000000..7a66238e0 --- /dev/null +++ b/solutions/tests/test_sum_positive_numbers.py @@ -0,0 +1,42 @@ +""" +test_sum_positive_numbers.py + +Unit tests for the sum_positive_numbers function. +""" + +import unittest +from solutions.sum_positive_numbers import sum_positive_numbers + + +class TestSumPositiveNumbers(unittest.TestCase): + """Tests for sum_positive_numbers function.""" + + def test_positive_numbers(self): + """Should return the sum of positive numbers.""" + self.assertEqual(sum_positive_numbers([1, 2, 3]), 6) + + def test_mixed_numbers(self): + """Should sum only positive numbers and ignore negatives.""" + self.assertEqual(sum_positive_numbers([1, -2, 3.5, 0, -1]), 4.5) + + def test_all_negative_numbers(self): + """Should return 0 if there are no positive numbers.""" + self.assertEqual(sum_positive_numbers([-10, -20, -30]), 0) + + def test_empty_list(self): + """Should return 0 for an empty list.""" + self.assertEqual(sum_positive_numbers([]), 0) + + def test_invalid_input_type(self): + """Should raise TypeError for non-list input.""" + with self.assertRaises(TypeError): + sum_positive_numbers("invalid") + + def test_non_numeric_elements(self): + """Should raise ValueError if list contains non-numeric elements.""" + with self.assertRaises(ValueError): + sum_positive_numbers([1, 2, "three"]) + + +if __name__ == "__main__": + unittest.main()