Skip to content

Commit

Permalink
Added new tests for the bubble sort and utils file
Browse files Browse the repository at this point in the history
  • Loading branch information
Nonso-M committed Jan 18, 2025
1 parent d310e8c commit d2549a9
Show file tree
Hide file tree
Showing 8 changed files with 222 additions and 88 deletions.
101 changes: 99 additions & 2 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ python = "^3.9"

[tool.poetry.group.dev.dependencies]
pytest = "^8.3.4"
pytest-cov = "^6.0.0"

[build-system]
requires = ["poetry-core>=1.0.0"]
Expand Down
8 changes: 6 additions & 2 deletions src/pysorting/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,12 @@

__version__ = version("pysorting")

from pysorting.bubblesort import bubble_sort
from pysorting.bubblesort import (
bubble_sort,
InvalidElementTypeError,
NonUniformTypeError,
)
from pysorting.quicksort import quick_sort


from pysorting.utils import find_fastest_sorting_function, sorting_time
from pysorting.utils import find_fastest_sorting_function, sorting_time, is_sorted
83 changes: 22 additions & 61 deletions src/pysorting/bubblesort.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,65 +4,25 @@
"""

# import numpy as np
from .utils import validate_list_elements


def bubble_sort(arr):
"""
Sorts a list of numbers in ascending order using the Bubble Sort algorithm.
Parameters
----------
arr : list
A list of numeric values to be sorted.
Returns
-------
list
A sorted list in ascending order.
Raises
------
TypeError
If the input is not a list.
ValueError
If the list contains non-numeric elements.
Examples
--------
>>> bubble_sort([4, 2, 7, 1, 3])
[1, 2, 3, 4, 7]
class InvalidElementTypeError(Exception):
"""Custom exception raised when elements are not strings or lists of strings."""

>>> bubble_sort([10, -3, 0, 5, 9])
[-3, 0, 5, 9, 10]
"""
try:
# Validate input type
# if not isinstance(arr, (list,np.ndarray)):
if not isinstance(arr, list):
raise TypeError("Input must be a list.")
def __init__(
self, message="All elements must be either a string or a list of strings."
):
self.message = message
super().__init__(self.message)

# Validate list elements
if not all(isinstance(x, (int, float, str)) for x in arr):
raise ValueError("All elements in the list must be numeric or be a string.")

n = len(arr)
for i in range(n):
swapped = False
for j in range(0, n - i - 1):
if arr[j] > arr[j + 1]:
arr[j], arr[j + 1] = arr[j + 1], arr[j] # Swap elements
swapped = True
if not swapped:
break
print("Done sorting the array")
return arr
class NonUniformTypeError(Exception):
"""Custom exception raised when elements are not strings or lists of strings."""

except TypeError as te:
raise (f"Some or all of the values in the list are not accepted")
except ValueError as ve:
print(f"ValueError: {ve}")
except Exception as e:
print(f"An unexpected error occurred: {e}")
def __init__(self, message="Elements are not of the same type."):
self.message = message
super().__init__(self.message)


def bubble_sort(arr, ascending=True):
Expand Down Expand Up @@ -96,14 +56,17 @@ def bubble_sort(arr, ascending=True):
>>> bubble_sort([10, -3, 0, 5, 9], order="descending")
[10, 9, 5, 0, -3]
"""
if not all(isinstance(x, (int, float, str)) for x in arr):
raise InvalidElementTypeError()

if not validate_list_elements(arr):
raise NonUniformTypeError()
try:
# Validate input type
if not isinstance(arr, list):
raise TypeError("Input must be a list.")
# if not isinstance(arr, list):
# raise TypeError("Input must be a list.")

# Validate list elements
if not all(isinstance(x, (int, float, str)) for x in arr):
raise ValueError("All elements in the list must be numeric or a string.")
# # Validate list elements

# Sorting logic
n = len(arr)
Expand All @@ -122,8 +85,6 @@ def bubble_sort(arr, ascending=True):
return arr

except TypeError as te:
raise TypeError(te)
except ValueError as ve:
raise ValueError(ve)
raise TypeError("Your data should all be of the same type")
except Exception as e:
raise Exception(f"An unexpected error occurred: {e}")
19 changes: 19 additions & 0 deletions src/pysorting/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,3 +80,22 @@ def is_sorted(lst, ascending=True):
return all(lst[i] <= lst[i + 1] for i in range(len(lst) - 1))
else:
return all(lst[i] >= lst[i + 1] for i in range(len(lst) - 1))


def validate_list_elements(elements):
"""
Validates if all elements in a list are either all numerical (int or float)
or all strings.
Parameters:
- elements (list): List of elements to validate.
Returns:
- bool: True if the list is valid, False otherwise.
"""
if all(isinstance(e, (int, float)) for e in elements):
return True # All elements are numerical
elif all(isinstance(e, str) for e in elements):
return True # All elements are strings
else:
return False
40 changes: 23 additions & 17 deletions tests/bubblesort_test.py
Original file line number Diff line number Diff line change
@@ -1,60 +1,66 @@
import pytest
from pysorting import bubble_sort
from pysorting import bubble_sort, InvalidElementTypeError, NonUniformTypeError


def test_sorted_list(text_data_sorted):
def test_sorted_list(test_data_sorted):
"""Test if a pre-sorted list remains unchanged."""
expected = [1, 2, 3, 4, 5, 6, 7, 8]
actual = bubble_sort(text_data_sorted)
actual = bubble_sort(test_data_sorted)

assert isinstance(actual, list)
assert actual == expected


def test_reverse_sorted_list(text_data1):
def test_reverse_sorted_list(test_data1):
"""Test if a reverse sorting works properly."""
expected = [8, 7, 6, 5, 4, 3, 2, 1]
actual = bubble_sort(text_data1, ascending=False)
actual = bubble_sort(test_data1, ascending=False)

assert isinstance(actual, list)
assert actual == expected


def test_unsorted_list(text_data1):
def test_unsorted_list(test_data1):
"""Test if an unsorted list is sorted correctly."""
expected = [1, 2, 3, 4, 5, 6, 7, 8]
actual = bubble_sort(text_data1)
actual = bubble_sort(test_data1)

assert isinstance(actual, list)
assert actual == expected


def test_single_element_list(text_data_single_element):
def test_single_element_list(test_data_single_element):
"""Test if a single-element list is handled correctly."""
expected = [5]
actual = bubble_sort(text_data_single_element, ascending=False)
actual = bubble_sort(test_data_single_element, ascending=False)

assert isinstance(actual, list)
assert len(actual) == 1
assert actual == expected


def test_empty_list(text_data_empty):
def test_empty_list(test_data_empty):
"""Test if an empty list is handled correctly."""

actual = bubble_sort(text_data_empty)
actual = bubble_sort(test_data_empty)

assert isinstance(actual, list)
assert len(actual) == 0


def test_value_error(text_data_error):
def test_type_error(test_data_error2):
"""Test if a TypeError is raised for non-list inputs."""
with pytest.raises(ValueError):
bubble_sort(text_data_error)
with pytest.raises(TypeError):
bubble_sort(test_data_error2)


def test_type_error(text_data_error2):
def test_invalid_type_error(test_invalid_error):
"""Test if a TypeError is raised for non-list inputs."""
with pytest.raises(TypeError):
bubble_sort(text_data_error2)
with pytest.raises(InvalidElementTypeError):
bubble_sort(test_invalid_error)


def test_non_uniform_error(test_nonuniform_error):
"""Test if a TypeError is raised for non-list inputs."""
with pytest.raises(NonUniformTypeError):
bubble_sort(test_nonuniform_error)
Loading

0 comments on commit d2549a9

Please sign in to comment.