Skip to content
Closed
7 changes: 7 additions & 0 deletions src/Tests/pytest.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[pytest]
pythonpath = . .. src
testpaths = tests
addopts = -v --tb=short
python_files = test_*.py
python_classes = Test*
python_functions = test_*
1 change: 1 addition & 0 deletions src/Tests/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pytest
7 changes: 7 additions & 0 deletions src/Tests/src/bubble_sort.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
def bubble_sort(array: list) -> list:
for index_1 in range(len(array)):
for index_2 in range(index_1 + 1, len(array)):
if array[index_1] > array[index_2]:
array[index_1], array[index_2] = array[index_2], array[index_1]

return array
27 changes: 27 additions & 0 deletions src/Tests/src/heap_sort.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
def heap_sort(array: list) -> list:
length = len(array)

for index in range(length // 2 - 1, -1, -1):
heapify(array, length, index)

for index in range(length - 1, 0, -1):
array[0], array[index] = array[index], array[0]
heapify(array, index, 0)

return array


def heapify(array: list, length: int, index: int) -> None:
largest = index
left = 2 * index + 1
right = 2 * index + 2

if left < length and array[left] > array[largest]:
largest = left

if right < length and array[right] > array[largest]:
largest = right

if largest != index:
array[index], array[largest] = array[largest], array[index]
heapify(array, length, largest)
10 changes: 10 additions & 0 deletions src/Tests/src/quick_sort.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
def quick_sort(array: list) -> list:
if len(array) <= 1:
return array

pivot = array[len(array) // 2]
left = [x for x in array if x < pivot]
middle = [x for x in array if x == pivot]
right = [x for x in array if x > pivot]

return quick_sort(left) + middle + quick_sort(right)
10 changes: 10 additions & 0 deletions src/Tests/src/selection_sort.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
def selection_sort(array: list) -> list:
for index_1 in range(len(array)):
min_idx = index_1
for index_2 in range(index_1 + 1, len(array)):
if array[index_2] < array[min_idx]:
min_idx = index_2

array[index_1], array[min_idx] = array[min_idx], array[index_1]

return array
Empty file added src/Tests/tests/__init__.py
Empty file.
31 changes: 31 additions & 0 deletions src/Tests/tests/test_heapsort.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
from Tests.src.heap_sort import heap_sort


def test_sort_empty_list() -> None:
assert heap_sort([]) == []


def test_sort_single_element() -> None:
assert heap_sort([5]) == [5]
assert heap_sort([-1]) == [-1]
assert heap_sort([0]) == [0]


def test_sort_positive_numbers() -> None:
assert heap_sort([3, 1, 4, 1, 5]) == [1, 1, 3, 4, 5]
assert heap_sort([5, 4, 3, 2, 1]) == [1, 2, 3, 4, 5]


def test_sort_negative_numbers() -> None:
assert heap_sort([-3, -1, -4, -1, -5]) == [-5, -4, -3, -1, -1]
assert heap_sort([-1, -2, -3, -4, -5]) == [-5, -4, -3, -2, -1]


def test_sort_mixed_numbers() -> None:
assert heap_sort([3, -1, 0, -2, 5]) == [-2, -1, 0, 3, 5]
assert heap_sort([0, -1, 1, -2, 2]) == [-2, -1, 0, 1, 2]


def test_sort_strings() -> None:
assert heap_sort(["banana", "apple", "cherry"]) == ["apple", "banana", "cherry"]
assert heap_sort(["z", "a", "m"]) == ["a", "m", "z"]
73 changes: 73 additions & 0 deletions src/Tests/tests/test_property_based.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import pytest
import random
from collections import Counter

from src.heap_sort import heap_sort
from src.quick_sort import quick_sort
from src.bubble_sort import bubble_sort
from src.selection_sort import selection_sort

SORTING_FUNCTIONS = [heap_sort, quick_sort, bubble_sort, selection_sort]


@pytest.fixture
def unsorted_lists() -> list[list]:
sizes = [5, 10, 15, 20, 30, 50]
lists = []
for size in sizes:
array = []
for _ in range(size):
array.append(random.randint(-100, 100))
lists.append(array)

return lists


@pytest.mark.parametrize("sorting_function", SORTING_FUNCTIONS)
def test_orderliness(sorting_function, unsorted_lists) -> None:
for unsorted_list in unsorted_lists:
sorted_array = sorting_function(unsorted_list)
for index in range(1, len(sorted_array)):
assert sorted_array[index] >= sorted_array[index - 1]


@pytest.mark.parametrize("sorting_function", SORTING_FUNCTIONS)
def test_elements_sameness(sorting_function, unsorted_lists) -> None:
for unsorted_list in unsorted_lists:
sorted_list = sorting_function(unsorted_list)
assert Counter(sorted_list) == Counter(unsorted_list)


@pytest.mark.parametrize("sorting_function", SORTING_FUNCTIONS)
def test_idempotency(sorting_function, unsorted_lists):
for unsorted_list in unsorted_lists:
first_sort = sorting_function(unsorted_list.copy())
second_sort = sorting_function(first_sort.copy())

assert first_sort == second_sort


@pytest.fixture(
params=[
[],
[1],
[1, 1, 1],
[1, 2, 3, 4, 5],
[5, 4, 3, 2, 1],
[1, 3, 2, 3, 1],
[-1, -5, 2, -3, 0],
[100, -100, 0, 50, -50],
[1] * 100,
list(range(100, 0, -1)),
]
)
def edge_case_list(request):
return request.param


@pytest.mark.parametrize("sorting_function", SORTING_FUNCTIONS)
def test_edge_cases(sorting_function, edge_case_list):
original = edge_case_list.copy()
sorted_list = sorting_function(edge_case_list)

assert sorted_list == sorted(original)
Loading