Skip to content

Commit

Permalink
Add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
realshouzy committed Apr 27, 2024
1 parent e893fd7 commit 8c6ecce
Show file tree
Hide file tree
Showing 14 changed files with 1,867 additions and 0 deletions.
Empty file added tests/__init__.py
Empty file.
Empty file added tests/algorithms/__init__.py
Empty file.
75 changes: 75 additions & 0 deletions tests/algorithms/searching_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#!/usr/bin/env python3
"""Tests for `datastructures._searching`."""
from __future__ import annotations

from typing import Iterator

import pytest

from nrw.algorithms._seraching import (
breadth_first_search,
depth_first_search,
linear_search,
)
from nrw.datastructures import Edge, Graph, List, Vertex


def test_linear_search() -> None:
lst: List[int] = List()
for i in range(5):
lst.append(i)

assert linear_search(lst, 3) == 3
assert lst.content == 3
assert linear_search(lst, 10) == 5
assert not lst.has_access


def test_depth_first_search() -> None:
graph: Graph = Graph()
vertex1: Vertex = Vertex("A")
graph.add_vertex(vertex1)
vertex2: Vertex = Vertex("B")
graph.add_vertex(vertex2)
vertex3: Vertex = Vertex("C")
graph.add_vertex(vertex3)
edge1: Edge = Edge(vertex1, vertex2, 1)
graph.add_edge(edge1)
edge2: Edge = Edge(vertex1, vertex3, 1)
graph.add_edge(edge2)
edge3: Edge = Edge(vertex2, vertex3, 1)
graph.add_edge(edge3)

expected_result: Iterator[Vertex] = iter((vertex1, vertex2, vertex3))
result: List[Vertex] = depth_first_search(graph, vertex1)
result.to_first()
while result.has_access:
assert result.content is next(expected_result)
result.next()


def test_breadth_first_search() -> None:
graph: Graph = Graph()
vertex1: Vertex = Vertex("A")
graph.add_vertex(vertex1)
vertex2: Vertex = Vertex("B")
graph.add_vertex(vertex2)
vertex3: Vertex = Vertex("C")
graph.add_vertex(vertex3)
edge1: Edge = Edge(vertex1, vertex2, 1)
graph.add_edge(edge1)
edge2: Edge = Edge(vertex1, vertex3, 1)
graph.add_edge(edge2)
edge3: Edge = Edge(vertex2, vertex3, 1)
graph.add_edge(edge3)

expected_result: Iterator[Vertex] = iter((vertex1, vertex2, vertex3))
result: List[Vertex] = breadth_first_search(graph, vertex1)
result.to_first()
while result.has_access:
assert result.content is next(expected_result)
result.next()


if __name__ == "__main__":
raise SystemExit(pytest.main())
154 changes: 154 additions & 0 deletions tests/algorithms/sorting_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
#!/usr/bin/env python3
"""Tests for `datastructures._sorting`."""
from __future__ import annotations

from typing import Callable

import pytest

from nrw.algorithms._sorting import (
bubble_sort,
insertion_sort,
merge_sort,
quick_sort,
selection_sort,
)
from nrw.datastructures import ComparableContentT, List


@pytest.fixture()
def empty_list() -> List[int]:
return List()


@pytest.fixture()
def sorted_list() -> List[int]:
lst: List[int] = List()
lst.append(1)
lst.append(2)
lst.append(3)
lst.append(3)
lst.append(5)
lst.append(10)
return lst


@pytest.fixture()
def unsorted_list() -> List[int]:
lst: List[int] = List()
lst.append(3)
lst.append(1)
lst.append(3)
lst.append(10)
lst.append(5)
return lst


def _is_sorted(lst: List[ComparableContentT]) -> bool:
lst.to_first()
while lst.has_access and lst._current.next_node is not None:
previous: ComparableContentT | None = lst.content
lst.next()
if previous > lst.content: # type: ignore[operator]
return False
return True


def _have_same_elements(
lst1: List[ComparableContentT],
lst2: List[ComparableContentT],
) -> bool:
elements_of_lst1: list[ComparableContentT] = []
lst1.to_first()
while lst1.has_access:
elements_of_lst1.append(lst1.content) # type: ignore[arg-type]
lst1.next()

elements_of_lst2: list[ComparableContentT] = []
lst2.to_first()
while lst2.has_access:
elements_of_lst2.append(lst2.content) # type: ignore[arg-type]
lst2.next()

return sorted(elements_of_lst1) == sorted(elements_of_lst2)


def _copy(lst: List[ComparableContentT]) -> List[ComparableContentT]:
copy: List[ComparableContentT] = List()
lst.to_first()
while lst.has_access:
copy.append(lst.content)
lst.next()
return copy


def test_is_sorted_on_empty_list(empty_list: List[int]) -> None:
assert _is_sorted(empty_list)


def test_is_sorted_on_sorted_list(sorted_list: List[int]) -> None:
assert _is_sorted(sorted_list)


def test_is_sorted_on_unsorted_list(unsorted_list: List[int]) -> None:
assert not _is_sorted(unsorted_list)


def test_have_same_elements() -> None:
lst1: List[int] = List()
lst1.append(1)
lst1.append(2)
lst1.append(3)

lst2: List[int] = List()
lst2.append(3)
lst2.append(1)
lst2.append(2)

assert _have_same_elements(lst1, lst2)

assert _have_same_elements(List[int](), List[int]())
assert not _have_same_elements(lst1, List[int]())


@pytest.mark.parametrize(
"sorting_algorithm",
[bubble_sort, insertion_sort, merge_sort, quick_sort, selection_sort],
)
def test_sorting_algorithm_on_empty_list(
sorting_algorithm: Callable[[List[int]], List[int]],
empty_list: List[int],
) -> None:
newly_sorted_list: List[int] = sorting_algorithm(empty_list)
assert _is_sorted(newly_sorted_list)
assert _have_same_elements(newly_sorted_list, empty_list)


@pytest.mark.parametrize(
"sorting_algorithm",
[bubble_sort, insertion_sort, merge_sort, quick_sort, selection_sort],
)
def test_sorting_algorithm_on_sorted_list(
sorting_algorithm: Callable[[List[int]], List[int]],
sorted_list: List[int],
) -> None:
newly_sorted_list: List[int] = sorting_algorithm(_copy(sorted_list))
assert _is_sorted(newly_sorted_list)
assert _have_same_elements(newly_sorted_list, sorted_list)


@pytest.mark.parametrize(
"sorting_algorithm",
[bubble_sort, insertion_sort, merge_sort, quick_sort, selection_sort],
)
def test_sorting_algorithm_on_unsorted_list(
sorting_algorithm: Callable[[List[int]], List[int]],
unsorted_list: List[int],
) -> None:
newly_sorted_list: List[int] = sorting_algorithm(_copy(unsorted_list))
assert _is_sorted(newly_sorted_list)
assert _have_same_elements(newly_sorted_list, unsorted_list)


if __name__ == "__main__":
raise SystemExit(pytest.main())
157 changes: 157 additions & 0 deletions tests/algorithms/traversal_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
#!/usr/bin/env python3
"""Tests for `datastructures._traversal`."""
from __future__ import annotations

from typing import TYPE_CHECKING, Callable, Iterator

import pytest

from nrw.algorithms._traversal import (
inorder,
levelorder,
postorder,
preorder,
reverse_inorder,
)
from nrw.datastructures import BinarySearchTree, BinaryTree

if TYPE_CHECKING:
from nrw.datastructures import List


@pytest.fixture()
def bst() -> BinarySearchTree[int]:
tree: BinarySearchTree[int] = BinarySearchTree()
tree.insert(1)
tree.insert(0)
tree.insert(2)
return tree


@pytest.fixture()
def binary_tree() -> BinaryTree[int]:
tree: BinaryTree[int] = BinaryTree()
tree.content = 1
tree.left_tree.content = 0
tree.right_tree.content = 2
return tree


@pytest.mark.parametrize("empty_tree", [BinaryTree[int](), BinarySearchTree[int]()])
@pytest.mark.parametrize(
"traverse",
[inorder, postorder, preorder, reverse_inorder, levelorder],
)
def test_traversal_on_empty_tree(
empty_tree: BinaryTree[int] | BinarySearchTree[int],
traverse: Callable[[BinaryTree[int] | BinarySearchTree[int]], List[int]],
) -> None:
assert traverse(empty_tree).is_empty


def test_inorder_traversal_on_binary_tree(binary_tree: BinaryTree[int]) -> None:
expected_result: Iterator[int] = iter((0, 1, 2))
result: List[int] = inorder(binary_tree)

result.to_first()
while result.has_access:
assert result.content == next(expected_result)
result.next()


def test_postorder_traversal_on_binary_tree(binary_tree: BinaryTree[int]) -> None:
expected_result: Iterator[int] = iter((0, 2, 1))
result: List[int] = postorder(binary_tree)

result.to_first()
while result.has_access:
assert result.content == next(expected_result)
result.next()


def test_preorder_traversal_on_binary_tree(binary_tree: BinaryTree[int]) -> None:
expected_result: Iterator[int] = iter((1, 0, 2))
result: List[int] = preorder(binary_tree)

result.to_first()
while result.has_access:
assert result.content == next(expected_result)
result.next()


def test_reverse_inorder_traversal_on_binary_tree(binary_tree: BinaryTree[int]) -> None:
expected_result: Iterator[int] = iter((2, 1, 0))
result: List[int] = reverse_inorder(binary_tree)

result.to_first()
while result.has_access:
assert result.content == next(expected_result)
result.next()


def test_levelorder_traversal_on_binary_tree(binary_tree: BinaryTree[int]) -> None:
expected_result: Iterator[int] = iter((1, 0, 2))
result: List[int] = levelorder(binary_tree)

result.to_first()
while result.has_access:
assert result.content == next(expected_result)
result.next()


def test_inorder_traversal_on_binary_search_tree(bst: BinarySearchTree[int]) -> None:
expected_result: Iterator[int] = iter((0, 1, 2))
result: List[int] = inorder(bst)

result.to_first()
while result.has_access:
assert result.content == next(expected_result)
result.next()


def test_postorder_traversal_on_binary_search_tree(bst: BinarySearchTree[int]) -> None:
expected_result: Iterator[int] = iter((0, 2, 1))
result: List[int] = postorder(bst)

result.to_first()
while result.has_access:
assert result.content == next(expected_result)
result.next()


def test_preorder_traversal_on_binary_search_tree(bst: BinarySearchTree[int]) -> None:
expected_result: Iterator[int] = iter((1, 0, 2))
result: List[int] = preorder(bst)

result.to_first()
while result.has_access:
assert result.content == next(expected_result)
result.next()


def test_reverse_inorder_traversal_on_binary_search_tree(
bst: BinarySearchTree[int],
) -> None:
expected_result: Iterator[int] = iter((2, 1, 0))
result: List[int] = reverse_inorder(bst)

result.to_first()
while result.has_access:
assert result.content == next(expected_result)
result.next()


def test_levelorder_traversal_on_binary_search_tree(
bst: BinarySearchTree[int],
) -> None:
expected_result: Iterator[int] = iter((1, 0, 2))
result: List[int] = levelorder(bst)

result.to_first()
while result.has_access:
assert result.content == next(expected_result)
result.next()


if __name__ == "__main__":
raise SystemExit(pytest.main())
Empty file.
Loading

0 comments on commit 8c6ecce

Please sign in to comment.