From 549a3290cdf6ce0721df99283fd98296dd29426d Mon Sep 17 00:00:00 2001 From: Joakim Persson Date: Sat, 13 Jul 2024 00:10:47 +0200 Subject: [PATCH] Omarbetade tester och tydligare funktions- och variabelnamn --- hanoi/hanoi.py | 63 +++++++++++++--------- hanoi/unittest_hanoi.py | 104 +++++++++++++++++++++--------------- hanoi/unittest_hanoi_old.py | 47 ++++++++++++++++ 3 files changed, 147 insertions(+), 67 deletions(-) create mode 100644 hanoi/unittest_hanoi_old.py diff --git a/hanoi/hanoi.py b/hanoi/hanoi.py index a621dfb..1b4a620 100644 --- a/hanoi/hanoi.py +++ b/hanoi/hanoi.py @@ -1,33 +1,48 @@ - -def hanoi(n, source, auxiliary, target): - # Example usage: - # hanoi(3, 'A', 'B', 'C') +def tower_of_hanoi(n, source, auxiliary, target): + """ + Solve the Tower of Hanoi puzzle with n disks. + + Parameters: + n (int): The number of disks to move. + source (str): The starting peg. + auxiliary (str): An intermediate peg. + target (str): The destination peg. + + Raises: + ValueError: If n is less than 1, indicating no disks to move. + """ if n < 1: - print(f"No disks, nothing to do") - return + raise ValueError("No disks to move. Please enter a positive integer.") + if n == 1: print(f"Move disk 1 from {source} to {target}") - return - # Move n-1 disks from source to auxiliary, so they are out of the way - hanoi(n - 1, source, target, auxiliary) - # Move the nth disk from source to target - print(f"Move disk {n} from {source} to {target}") - # Move the n-1 disks that we left on auxiliary to target - hanoi(n - 1, auxiliary, source, target) + else: + tower_of_hanoi(n - 1, source, target, auxiliary) + print(f"Move disk {n} from {source} to {target}") + tower_of_hanoi(n - 1, auxiliary, source, target) -def get_hanoi_input(): - # Returns a positive integer, otherwise throws an exception - while True: +def prompt_for_integer(): + """ + Prompts the user to enter a positive integer until a valid input is received. + + Returns: + int: A positive integer entered by the user. + + Raises: + ValueError: If the entered input is anything else, for instance a negative integer or a string. + """ + while True: user_input = input("Please enter an integer: ") try: user_integer = int(user_input) - return user_integer + if user_integer > 0: + return user_integer + else: + print("The number must be positive.") except ValueError: - print("That's not a valid integer. Please try again.") + print("Invalid literal for int() with base 10. Please enter an integer.") -if __name__== "__main__": - # Call the new function to get the input - user_integer = get_hanoi_input() - # Now call hanoi with the obtained integer - hanoi(user_integer, 'A', 'B', 'C') - \ No newline at end of file + +if __name__ == "__main__": + user_integer = prompt_for_integer() + tower_of_hanoi(user_integer, 'A', 'B', 'C') diff --git a/hanoi/unittest_hanoi.py b/hanoi/unittest_hanoi.py index 72d1da9..4c36505 100644 --- a/hanoi/unittest_hanoi.py +++ b/hanoi/unittest_hanoi.py @@ -1,47 +1,65 @@ import unittest import io -from unittest.mock import patch -from hanoi import hanoi, get_hanoi_input +import sys +from hanoi import tower_of_hanoi, prompt_for_integer -class TestHanoi(unittest.TestCase): - - def test_hanoi_zero_disks(self): - expected_output = "No disks, nothing to do\n" - # with self.assertRaises(SystemExit): - with unittest.mock.patch('sys.stdout', new=io.StringIO()) as mock_stdout: - hanoi(0, 'A', 'B', 'C') - - def test_hanoi_one_disk(self): - expected_output = "Move disk 1 from A to C\n" - with unittest.mock.patch('sys.stdout', new=io.StringIO()) as mock_stdout: - hanoi(1, 'A', 'B', 'C') - self.assertEqual(mock_stdout.getvalue(), expected_output) - - def test_hanoi_two_disks(self): - expected_output = "Move disk 1 from A to B\nMove disk 2 from A to C\nMove disk 1 from B to C\n" - with unittest.mock.patch('sys.stdout', new=io.StringIO()) as mock_stdout: - hanoi(2, 'A', 'B', 'C') - self.assertEqual(mock_stdout.getvalue(), expected_output) - - def test_hanoi_three_disks(self): - expected_output = "Move disk 1 from A to C\nMove disk 2 from A to B\nMove disk 1 from C to B\nMove disk 3 from A to C\nMove disk 1 from B to A\nMove disk 2 from B to C\nMove disk 1 from A to C\n" - with unittest.mock.patch('sys.stdout', new=io.StringIO()) as mock_stdout: - hanoi(3, 'A', 'B', 'C') - self.assertEqual(mock_stdout.getvalue(), expected_output) - - def test_hanoi_negative_input(self): - expected_output = "No disks, nothing to do\n" - # with self.assertRaises(SystemExit): - with unittest.mock.patch('sys.stdout', new=io.StringIO()) as mock_stdout: - hanoi(-1, 'A', 'B', 'C') - - def test_get_hanoi_input_valid_integer(self): - with unittest.mock.patch('builtins.input', return_value='4'): - self.assertEqual(get_hanoi_input(), 4) - - def test_get_hanoi_input_invalid_input(self): - with unittest.mock.patch('builtins.input', side_effect=['abc', '5']): - self.assertEqual(get_hanoi_input(), 5) +class TestTowerOfHanoi(unittest.TestCase): + """ + Explanation of Tests: -if __name__ == "__main__": - unittest.main() + test_valid_input(): + This test checks the core functionality by moving 3 disks using tower_of_hanoi. + It asserts that the function completes without raising errors. + + test_edge_case_single_disk(): + This handles the base case of a single disk, ensuring the correct move + is printed ("Move disk 1 from A to C"). + + test_invalid_input_zero_disks(): + This checks that the function raises a ValueError when given zero disks. + + test_prompt_for_integer_valid(): + Tests the input function with valid integer input ("3") and asserts it + returns the correct value (3). + + test_prompt_for_integer_invalid_negative(): + Checks for handling negative integers, expecting a ValueError. + + test_prompt_for_integer_invalid_string(): + Tests that invalid string input is handled gracefully and eventually + leads to a valid integer being returned. + """ + + def test_valid_input(self): + self.assertEqual(tower_of_hanoi(3, 'A', 'B', 'C'), None) # Example with 3 disks + + def test_edge_case_single_disk(self): + expected_output = "Move disk 1 from A to C\n" + captured_output = io.StringIO() + sys.stdout = captured_output + tower_of_hanoi(1, 'A', 'B', 'C') + sys.stdout = sys.__stdout__ # Reset stdout + self.assertEqual(captured_output.getvalue(), expected_output) + + def test_invalid_input_zero_disks(self): + with self.assertRaises(ValueError): + tower_of_hanoi(0, 'A', 'B', 'C') + + def test_prompt_for_integer_valid(self): + with io.StringIO("3\n") as mock_stdin: + sys.stdin = mock_stdin + self.assertEqual(prompt_for_integer(), 3) + + def test_prompt_for_integer_invalid_negative(self): + with io.StringIO("-2\n1\n") as mock_stdin: + sys.stdin = mock_stdin + self.assertEqual(prompt_for_integer(), 1) # Should eventually get a valid integer + + + def test_prompt_for_integer_invalid_string(self): + with io.StringIO("abc\n3\n") as mock_stdin: + sys.stdin = mock_stdin + self.assertEqual(prompt_for_integer(), 3) # Should eventually get a valid integer + +if __name__ == '__main__': + unittest.main() diff --git a/hanoi/unittest_hanoi_old.py b/hanoi/unittest_hanoi_old.py new file mode 100644 index 0000000..5e3b418 --- /dev/null +++ b/hanoi/unittest_hanoi_old.py @@ -0,0 +1,47 @@ +import unittest +import io +from unittest.mock import patch +from hanoi import hanoi, prompt_for_integer + +class TestHanoi(unittest.TestCase): + + def test_hanoi_zero_disks(self): + expected_output = "No disks, nothing to do\n" + # with self.assertRaises(SystemExit): + with unittest.mock.patch('sys.stdout', new=io.StringIO()) as mock_stdout: + hanoi(0, 'A', 'B', 'C') + + def test_hanoi_one_disk(self): + expected_output = "Move disk 1 from A to C\n" + with unittest.mock.patch('sys.stdout', new=io.StringIO()) as mock_stdout: + hanoi(1, 'A', 'B', 'C') + self.assertEqual(mock_stdout.getvalue(), expected_output) + + def test_hanoi_two_disks(self): + expected_output = "Move disk 1 from A to B\nMove disk 2 from A to C\nMove disk 1 from B to C\n" + with unittest.mock.patch('sys.stdout', new=io.StringIO()) as mock_stdout: + hanoi(2, 'A', 'B', 'C') + self.assertEqual(mock_stdout.getvalue(), expected_output) + + def test_hanoi_three_disks(self): + expected_output = "Move disk 1 from A to C\nMove disk 2 from A to B\nMove disk 1 from C to B\nMove disk 3 from A to C\nMove disk 1 from B to A\nMove disk 2 from B to C\nMove disk 1 from A to C\n" + with unittest.mock.patch('sys.stdout', new=io.StringIO()) as mock_stdout: + hanoi(3, 'A', 'B', 'C') + self.assertEqual(mock_stdout.getvalue(), expected_output) + + def test_hanoi_negative_input(self): + expected_output = "No disks, nothing to do\n" + # with self.assertRaises(SystemExit): + with unittest.mock.patch('sys.stdout', new=io.StringIO()) as mock_stdout: + hanoi(-1, 'A', 'B', 'C') + + def test_prompt_for_integer_valid_integer(self): + with unittest.mock.patch('builtins.input', return_value='4'): + self.assertEqual(prompt_for_integer(), 4) + + def test_prompt_for_integer_invalid_input(self): + with unittest.mock.patch('builtins.input', side_effect=['abc', '5']): + self.assertEqual(prompt_for_integer(), 5) + +if __name__ == "__main__": + unittest.main()