Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
name: Tests

on:
push:
branches: [ main, master ]
pull_request:
branches: [ main, master ]

jobs:
test:
runs-on: ubuntu-latest

strategy:
matrix:
python-version: ["3.12"]

steps:
- uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}

- name: Install pytest
run: |
python -m pip install --upgrade pip
pip install pytest

- name: Run tests
run: |
python -m pytest -v
4 changes: 4 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,7 @@ target-version = "py312"
"RET", # Хорошие практики возврата
"SIM", # Общие правила упрощения
]

[tool.pytest.ini_options]
testpaths = ["tests"]
pythonpath = ["src"]
27 changes: 27 additions & 0 deletions src/tests_pytest_6/heap_sort.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
def heapify(arr, n, i):
largest = i
left = 2 * i + 1
right = 2 * i + 2

if left < n and arr[i] < arr[left]:
largest = left

if right < n and arr[largest] < arr[right]:
largest = right

if largest != i:
arr[i], arr[largest] = arr[largest], arr[i]
heapify(arr, n, largest)


def heap_sort(arr):
n = len(arr)

for i in range(n // 2 - 1, -1, -1):
heapify(arr, n, i)

for i in range(n - 1, 0, -1):
arr[i], arr[0] = arr[0], arr[i]

heapify(arr, i, 0)
return arr
30 changes: 30 additions & 0 deletions src/tests_pytest_6/merge_sort.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
def merge_sort(arr):
if len(arr) > 1:
mid = len(arr) // 2
left = arr[:mid]
right = arr[mid:]

merge_sort(left)
merge_sort(right)

i = j = k = 0

while i < len(left) and j < len(right):
if left[i] < right[j]:
arr[k] = left[i]
i += 1
else:
arr[k] = right[j]
j += 1
k += 1

while i < len(left):
arr[k] = left[i]
i += 1
k += 1

while j < len(right):
arr[k] = right[j]
j += 1
k += 1
return arr
65 changes: 65 additions & 0 deletions src/tests_pytest_6/quick_sort.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
def partition(array, start, end):
pivot = array[start]
low = start + 1
high = end

while True:
while low <= high and array[high] >= pivot:
high = high - 1

while low <= high and array[low] <= pivot:
low = low + 1

if low <= high:
array[low], array[high] = array[high], array[low]
else:
break

array[start], array[high] = array[high], array[start]

return high


def quick_sort(array, start=0, end=None):
if end is None:
end = len(array) - 1

if start >= end:
return array

p = partition(array, start, end)
quick_sort(array, start, p - 1)
quick_sort(array, p + 1, end)
return array


def merge_sort(arr):
if len(arr) > 1:
mid = len(arr) // 2
left = arr[:mid]
right = arr[mid:]

merge_sort(left)
merge_sort(right)

i = j = k = 0

while i < len(left) and j < len(right):
if left[i] < right[j]:
arr[k] = left[i]
i += 1
else:
arr[k] = right[j]
j += 1
k += 1

while i < len(left):
arr[k] = left[i]
i += 1
k += 1

while j < len(right):
arr[k] = right[j]
j += 1
k += 1
return arr
118 changes: 118 additions & 0 deletions tests/test_heap_sort.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
import random

import pytest
from tests_pytest_6.heap_sort import heap_sort, heapify
from tests_pytest_6.merge_sort import merge_sort
from tests_pytest_6.quick_sort import quick_sort

# unit тесты


def test_heapify_work():
"""Тест функции heapify на корректность"""
arr = [1, 3, 2]
heapify(arr, 3, 0)
assert arr == [3, 1, 2]


def test_duplicate_elements():
"""Тест с дубликатами"""
assert heap_sort([3, 1, 2, 3, 1]) == [1, 1, 2, 3, 3]


def test_negative_numbers():
"""Тест с отрицательными числами"""
assert heap_sort([-5, 3, -1, 0, 2]) == [-5, -1, 0, 2, 3]


# крайние случаи


def test_empty_list():
"""Тест пустого списка"""
assert heap_sort([]) == []


def test_single_element():
"""Тест одного элемента"""
assert heap_sort([5]) == [5]


def test_sorted_list():
"""Тест уже отсортированного списка"""
assert heap_sort([1, 2, 3, 4, 5]) == [1, 2, 3, 4, 5]


def test_reverse_sorted():
"""Тест обратно отсортированного списка"""
assert heap_sort([5, 4, 3, 2, 1]) == [1, 2, 3, 4, 5]


def test_large_list():
"""Тест большого списка"""
lst = list(range(1000, 0, -1))
expected = list(range(1, 1001))
assert heap_sort(lst) == expected


# параметризованный тест


@pytest.mark.parametrize(
"arr, expected",
[([], []), ([5], [5]), ([3, 1], [1, 3]), ([3, 1, 5, 7], [1, 3, 5, 7])],
)
def test_heap_sort_main(arr, expected):
assert heap_sort(arr) == expected


# property-based тесты


def test_property_idempotence():
"""Повторная сортировка не меняет результат"""
for _ in range(100):
lst = [random.randint(-1000, 1000) for _ in range(random.randint(0, 100))]
sorted_once = heap_sort(lst.copy())
sorted_twice = heap_sort(sorted_once.copy())
assert sorted_once == sorted_twice


def test_property_length_preservation():
"""Длина списка сохраняется"""
for _ in range(100):
lst = [random.randint(-1000, 1000) for _ in range(random.randint(0, 100))]
assert len(heap_sort(lst)) == len(lst)


def test_property_sorted_order():
"""Результат должен быть отсортирован"""
for _ in range(100):
lst = [random.randint(-1000, 1000) for _ in range(random.randint(1, 100))]
sorted_lst = heap_sort(lst)
for i in range(1, len(sorted_lst)):
assert sorted_lst[i - 1] <= sorted_lst[i]


def test_against_builtin_sort():
"""Сравнение со встроенной сортировкой Python"""
for _ in range(100):
lst = [random.randint(-1000, 1000) for _ in range(random.randint(0, 100))]
assert heap_sort(lst.copy()) == sorted(lst)


# Сравнение с другими сортировками


def test_against_quick_sort():
"""Сравнение с quick_sort"""
for _ in range(50):
lst = [random.randint(-100, 100) for _ in range(random.randint(0, 50))]
assert heap_sort(lst.copy()) == quick_sort(lst.copy())


def test_against_merge_sort():
"""Сравнение с merge_sort"""
for _ in range(50):
lst = [random.randint(-100, 100) for _ in range(random.randint(0, 50))]
assert heap_sort(lst.copy()) == merge_sort(lst.copy())