176 lines
5.9 KiB
Python
176 lines
5.9 KiB
Python
import unittest
|
||
from utils.algo_context import AlgoContext
|
||
from utils.algo_int import Int
|
||
from utils.algo_array import Array
|
||
|
||
|
||
class TestArray(unittest.TestCase):
|
||
|
||
def setUp(self):
|
||
self.ctx = AlgoContext()
|
||
|
||
# ------------------------------------------------------------------
|
||
# Erzeugung
|
||
# ------------------------------------------------------------------
|
||
|
||
def test_from_list(self):
|
||
z = Array([3, 1, 4, 1, 5], self.ctx)
|
||
self.assertEqual(len(z), 5)
|
||
self.assertEqual(z[0].value, 3)
|
||
self.assertEqual(z[4].value, 5)
|
||
|
||
def test_random(self):
|
||
z = Array.random(20, 0, 99, self.ctx)
|
||
self.assertEqual(len(z), 20)
|
||
for cell in z:
|
||
self.assertGreaterEqual(cell.value, 0)
|
||
self.assertLessEqual(cell.value, 99)
|
||
|
||
def test_sorted(self):
|
||
z = Array.sorted(5, self.ctx)
|
||
values = [z[i].value for i in range(5)]
|
||
self.assertEqual(values, [0, 1, 2, 3, 4])
|
||
|
||
def test_from_file(self):
|
||
z = Array.from_file("data/seq0.txt", self.ctx)
|
||
self.assertGreater(len(z), 0)
|
||
|
||
def test_random_uses_no_write_counts(self):
|
||
"""Fabrikmethoden sollen keine Schreibzugriffe verzeichnen."""
|
||
z = Array.random(10, 0, 9, self.ctx)
|
||
self.assertEqual(self.ctx.writes, 0)
|
||
|
||
# ------------------------------------------------------------------
|
||
# Zugriff
|
||
# ------------------------------------------------------------------
|
||
|
||
def test_getitem_returns_int_cell(self):
|
||
z = Array([10, 20], self.ctx)
|
||
cell = z[0]
|
||
self.assertIsInstance(cell, Int)
|
||
self.assertEqual(cell.value, 10)
|
||
|
||
def test_getitem_with_int_index(self):
|
||
z = Array([10, 20, 30], self.ctx)
|
||
i = Int(2, self.ctx)
|
||
self.assertEqual(z[i].value, 30)
|
||
|
||
def test_getitem_no_read_count(self):
|
||
"""Array-Zugriff allein soll keinen read-Zähler erhöhen."""
|
||
z = Array([5, 6, 7], self.ctx)
|
||
_ = z[0]
|
||
self.assertEqual(self.ctx.reads, 0)
|
||
|
||
def test_setitem_plain_int(self):
|
||
z = Array([1, 2, 3], self.ctx)
|
||
z[0] = 99
|
||
self.assertEqual(z[0].value, 99)
|
||
self.assertEqual(self.ctx.writes, 1)
|
||
self.assertEqual(self.ctx.reads, 0)
|
||
|
||
def test_setitem_int_object(self):
|
||
z = Array([1, 2, 3], self.ctx)
|
||
v = Int(42, self.ctx)
|
||
z[1] = v
|
||
self.assertEqual(z[1].value, 42)
|
||
self.assertEqual(self.ctx.writes, 1)
|
||
self.assertEqual(self.ctx.reads, 1)
|
||
|
||
def test_setitem_cell_to_cell(self):
|
||
"""z[i] = z[j] kopiert den Wert (keine Alias-Referenz)."""
|
||
z = Array([10, 20], self.ctx)
|
||
z[0] = z[1]
|
||
self.assertEqual(z[0].value, 20)
|
||
# Wert ändern – z[1] darf sich nicht mitändern
|
||
z[0] = 99
|
||
self.assertEqual(z[1].value, 20)
|
||
|
||
# ------------------------------------------------------------------
|
||
# Swap
|
||
# ------------------------------------------------------------------
|
||
|
||
def test_swap_exchanges_values(self):
|
||
z = Array([1, 2, 3, 4, 5], self.ctx)
|
||
z.swap(0, 4)
|
||
self.assertEqual(z[0].value, 5)
|
||
self.assertEqual(z[4].value, 1)
|
||
|
||
def test_swap_counts_reads_and_writes(self):
|
||
z = Array([1, 2], self.ctx)
|
||
z.swap(0, 1)
|
||
self.assertEqual(self.ctx.reads, 2)
|
||
self.assertEqual(self.ctx.writes, 2)
|
||
|
||
def test_swap_with_int_indices(self):
|
||
z = Array([10, 20, 30], self.ctx)
|
||
i = Int(0, self.ctx)
|
||
j = Int(2, self.ctx)
|
||
z.swap(i, j)
|
||
self.assertEqual(z[0].value, 30)
|
||
self.assertEqual(z[2].value, 10)
|
||
|
||
# ------------------------------------------------------------------
|
||
# Vergleich über Array-Zellen (zählt beim Int, nicht beim Array)
|
||
# ------------------------------------------------------------------
|
||
|
||
def test_cell_comparison_counts_in_ctx(self):
|
||
z = Array([5, 3], self.ctx)
|
||
result = z[0] > z[1]
|
||
self.assertTrue(result)
|
||
self.assertEqual(self.ctx.comparisons, 1)
|
||
self.assertEqual(self.ctx.reads, 2)
|
||
|
||
# ------------------------------------------------------------------
|
||
# Iteration
|
||
# ------------------------------------------------------------------
|
||
|
||
def test_iteration(self):
|
||
z = Array([1, 2, 3], self.ctx)
|
||
values = [c.value for c in z]
|
||
self.assertEqual(values, [1, 2, 3])
|
||
|
||
# ------------------------------------------------------------------
|
||
# Länge
|
||
# ------------------------------------------------------------------
|
||
|
||
def test_len(self):
|
||
z = Array([1, 2, 3, 4], self.ctx)
|
||
self.assertEqual(len(z), 4)
|
||
|
||
def test_length_returns_int(self):
|
||
z = Array([1, 2, 3], self.ctx)
|
||
n = z.length()
|
||
self.assertIsInstance(n, Int)
|
||
self.assertEqual(n.value, 3)
|
||
|
||
|
||
class TestArrayIntegration(unittest.TestCase):
|
||
"""Bubble Sort als Integrationstest für das gesamte Framework."""
|
||
|
||
def test_bubble_sort_produces_correct_result(self):
|
||
import sys, os
|
||
sys.path.insert(0, os.path.join(os.path.dirname(__file__),
|
||
'../vorlesung/L02_elementares_sortieren'))
|
||
from bubble_sorting import bubble_sort
|
||
ctx = AlgoContext()
|
||
z = Array([5, 3, 1, 4, 2], ctx)
|
||
bubble_sort(z, ctx)
|
||
values = [z[i].value for i in range(len(z))]
|
||
self.assertEqual(values, [1, 2, 3, 4, 5])
|
||
|
||
def test_bubble_sort_counts_comparisons(self):
|
||
import sys, os
|
||
sys.path.insert(0, os.path.join(os.path.dirname(__file__),
|
||
'../vorlesung/L02_elementares_sortieren'))
|
||
from bubble_sorting import bubble_sort
|
||
ctx = AlgoContext()
|
||
z = Array([5, 4, 3, 2, 1], ctx) # worst case
|
||
bubble_sort(z, ctx)
|
||
# n=5: maximal n*(n-1)/2 = 10 Vergleiche
|
||
self.assertGreater(ctx.comparisons, 0)
|
||
self.assertLessEqual(ctx.comparisons, 10)
|
||
|
||
|
||
if __name__ == "__main__":
|
||
unittest.main()
|