diff --git a/chatgpt-unit-tests-python/README.md b/chatgpt-unit-tests-python/README.md new file mode 100644 index 0000000000..d0727a0c4d --- /dev/null +++ b/chatgpt-unit-tests-python/README.md @@ -0,0 +1,3 @@ +# Write Unit Tests for Your Python Code With ChatGPT + +This folder provides the code examples for the Real Python tutorial [Write Unit Tests for Your Python Code With ChatGPT](https://realpython.com/chatgpt-unit-tests-python/). diff --git a/chatgpt-unit-tests-python/calculations.py b/chatgpt-unit-tests-python/calculations.py new file mode 100644 index 0000000000..f247ebe6bc --- /dev/null +++ b/chatgpt-unit-tests-python/calculations.py @@ -0,0 +1,36 @@ +from collections import Counter + + +def add(x, y): + return x + y + + +def subtract(x, y): + return x - y + + +def multiply(x, y): + return x * y + + +def divide(x, y): + if y == 0: + raise ValueError("Cannot divide by zero.") + return x / y + + +def mean(data): + return sum(data) / len(data) + + +def median(data): + n = len(data) + index = n // 2 + if n % 2: + return sorted(data)[index] + return sum(sorted(data)[index - 1 : index + 1]) / 2 + + +def mode(data): + c = Counter(data) + return [k for k, v in c.items() if v == c.most_common(1)[0][1]] diff --git a/chatgpt-unit-tests-python/fizzbuzz.py b/chatgpt-unit-tests-python/fizzbuzz.py new file mode 100644 index 0000000000..b8f820c60b --- /dev/null +++ b/chatgpt-unit-tests-python/fizzbuzz.py @@ -0,0 +1,9 @@ +def fizzbuzz(number): + if number % 15 == 0: + return "fizz buzz" + elif number % 3 == 0: + return "fizz" + elif number % 5 == 0: + return "buzz" + else: + return number diff --git a/chatgpt-unit-tests-python/fizzbuzz_doctest.py b/chatgpt-unit-tests-python/fizzbuzz_doctest.py new file mode 100644 index 0000000000..5a9084d20a --- /dev/null +++ b/chatgpt-unit-tests-python/fizzbuzz_doctest.py @@ -0,0 +1,38 @@ +def fizzbuzz(number): + """Solves the FizzBuzz problem. + + Return "fizz" for numbers divisible by 3, + "buzz" for numbers divisible by 5, + "fizz buzz" for numbers divisible by both, + and the number itself otherwise. + + >>> fizzbuzz(3) + 'fizz' + >>> fizzbuzz(5) + 'buzz' + >>> fizzbuzz(15) + 'fizz buzz' + >>> fizzbuzz(4) + 4 + >>> fizzbuzz(30) + 'fizz buzz' + >>> fizzbuzz(9) + 'fizz' + >>> fizzbuzz(10) + 'buzz' + """ + + if number % 15 == 0: + return "fizz buzz" + elif number % 3 == 0: + return "fizz" + elif number % 5 == 0: + return "buzz" + else: + return number + + +if __name__ == "__main__": + import doctest + + doctest.testmod() diff --git a/chatgpt-unit-tests-python/interval.py b/chatgpt-unit-tests-python/interval.py new file mode 100644 index 0000000000..fff0c3c8f2 --- /dev/null +++ b/chatgpt-unit-tests-python/interval.py @@ -0,0 +1,22 @@ +import pytest + + +def in_interval(number: int, start: int, end: int) -> bool: + return start <= number <= end + + +@pytest.mark.parametrize( + "number, start, end, expected", + [ + (5, 1, 10, True), # Test case inside the interval + (1, 1, 10, True), # Edge case: number equals start + (10, 1, 10, True), # Edge case: number equals end + (0, 1, 10, False), # Number below the interval + (11, 1, 10, False), # Number above the interval + (5, 5, 5, True), # Edge case: start equals end equals number + (-1, -5, 5, True), # Test case with negative numbers + (-6, -5, 5, False), # Number below the interval with negatives + ], +) +def test_in_interval(number, start, end, expected): + assert in_interval(number, start, end) == expected diff --git a/chatgpt-unit-tests-python/prime.py b/chatgpt-unit-tests-python/prime.py new file mode 100644 index 0000000000..e8686cc7be --- /dev/null +++ b/chatgpt-unit-tests-python/prime.py @@ -0,0 +1,32 @@ +import pytest + + +def is_prime(number: int) -> bool: + if number <= 1: + return False + for i in range(2, int(number**0.5) + 1): + if number % i == 0: + return False + return True + + +@pytest.mark.parametrize( + "number, expected", + [ + (2, True), # Smallest prime + (3, True), # Prime + (4, False), # Composite (2*2) + (5, True), # Prime + (11, True), # Prime + (12, False), # Composite (2*6) + (13, True), # Prime + (25, False), # Composite (5*5) + (29, True), # Prime + (1, False), # Not prime by definition + (0, False), # Not prime + (-1, False), # Negative number + (-11, False), # Negative number + ], +) +def test_is_prime(number, expected): + assert is_prime(number) == expected diff --git a/chatgpt-unit-tests-python/readers.py b/chatgpt-unit-tests-python/readers.py new file mode 100644 index 0000000000..73de7825e9 --- /dev/null +++ b/chatgpt-unit-tests-python/readers.py @@ -0,0 +1,10 @@ +import json + + +class JSONReader: + def __init__(self, filename): + self.filename = filename + + def read(self): + with open(self.filename, encoding="utf-8") as file: + return json.load(file) diff --git a/chatgpt-unit-tests-python/test_calculations.py b/chatgpt-unit-tests-python/test_calculations.py new file mode 100644 index 0000000000..d555421cef --- /dev/null +++ b/chatgpt-unit-tests-python/test_calculations.py @@ -0,0 +1,59 @@ +import unittest + +from calculations import add, divide, mean, median, mode, multiply, subtract + + +class TestArithmeticOperations(unittest.TestCase): + def test_add(self): + self.assertEqual(add(10, 5), 15) + self.assertEqual(add(-1, 1), 0) + self.assertEqual(add(-1, -1), -2) + + def test_subtract(self): + self.assertEqual(subtract(10, 5), 5) + self.assertEqual(subtract(-1, 1), -2) + self.assertEqual(subtract(-1, -1), 0) + + def test_multiply(self): + self.assertEqual(multiply(10, 5), 50) + self.assertEqual(multiply(-1, 1), -1) + self.assertEqual(multiply(-1, -1), 1) + + def test_divide(self): + self.assertEqual(divide(10, 5), 2) + self.assertEqual(divide(-1, 1), -1) + self.assertEqual(divide(-1, -1), 1) + with self.assertRaises(ValueError): + divide(10, 0) + + +class TestStatisticalOperations(unittest.TestCase): + def test_mean(self): + self.assertEqual(mean([1, 2, 3, 4, 5]), 3) + self.assertEqual(mean([1, 2, 3, 4, 5, 6]), 3.5) + + def test_median_odd(self): + self.assertEqual(median([1, 3, 3, 6, 7, 8, 9]), 6) + + def test_median_even(self): + self.assertEqual(median([1, 2, 3, 4, 5, 6, 8, 9]), 4.5) + + def test_median_unsorted(self): + self.assertEqual(median([7, 1, 3, 3, 2, 6]), 3) + + def test_mode_single(self): + self.assertEqual(mode([1, 2, 2, 3, 4, 4, 4, 5]), [4]) + + def test_mode_multiple(self): + self.assertEqual(set(mode([1, 1, 2, 3, 4, 4, 5, 5])), {1, 4, 5}) + + +def load_tests(loader, tests, pattern): + suite = unittest.TestSuite() + # suite.addTests(loader.loadTestsFromTestCase(TestArithmeticOperations)) + suite.addTests(loader.loadTestsFromTestCase(TestStatisticalOperations)) + return suite + + +if __name__ == "__main__": + unittest.main() diff --git a/chatgpt-unit-tests-python/test_fizzbuzz_pytest.py b/chatgpt-unit-tests-python/test_fizzbuzz_pytest.py new file mode 100644 index 0000000000..6faad26f38 --- /dev/null +++ b/chatgpt-unit-tests-python/test_fizzbuzz_pytest.py @@ -0,0 +1,41 @@ +import pytest + +from fizzbuzz import fizzbuzz + +# def test_fizzbuzz_with_number_divisible_by_15(): +# assert fizzbuzz(30) == "fizz buzz" + + +# def test_fizzbuzz_with_number_divisible_by_3(): +# assert fizzbuzz(9) == "fizz" + + +# def test_fizzbuzz_with_number_divisible_by_5(): +# assert fizzbuzz(10) == "buzz" + + +# def test_fizzbuzz_with_number_not_divisible_by_3_or_5(): +# assert fizzbuzz(4) == 4 + + +# def test_fizzbuzz_with_zero(): +# assert fizzbuzz(0) == "fizz buzz" + + +@pytest.mark.parametrize( + "input,expected", + [ + (30, "fizz buzz"), # Divisible by 15 + (9, "fizz"), # Divisible by 3 + (10, "buzz"), # Divisible by 5 + (4, 4), # Not divisible by 3 or 5 + (0, "fizz buzz"), # Edge case: 0 (divisible by 15) + (33, "fizz"), # Additional case: Divisible by 3 + (55, "buzz"), # Additional case: Divisible by 5 + (98, 98), # Additional case: Not divisible by 3 or 5 + ], +) +def test_fizzbuzz(input, expected): + assert ( + fizzbuzz(input) == expected + ), f"Expected {expected} for input {input}" diff --git a/chatgpt-unit-tests-python/test_fizzbuzz_unittest.py b/chatgpt-unit-tests-python/test_fizzbuzz_unittest.py new file mode 100644 index 0000000000..4f30fd74c8 --- /dev/null +++ b/chatgpt-unit-tests-python/test_fizzbuzz_unittest.py @@ -0,0 +1,32 @@ +import unittest + +from fizzbuzz import fizzbuzz + + +class TestFizzBuzz(unittest.TestCase): + def test_fizz(self): + """Test numbers divisible by 3 but not by 5""" + self.assertEqual(fizzbuzz(3), "fizz") + self.assertEqual(fizzbuzz(6), "fizz") + self.assertNotEqual(fizzbuzz(15), "fizz") + + def test_buzz(self): + """Test numbers divisible by 5 but not by 3""" + self.assertEqual(fizzbuzz(5), "buzz") + self.assertEqual(fizzbuzz(10), "buzz") + self.assertNotEqual(fizzbuzz(15), "buzz") + + def test_fizz_buzz(self): + """Test numbers divisible by both 3 and 5""" + self.assertEqual(fizzbuzz(15), "fizz buzz") + self.assertEqual(fizzbuzz(30), "fizz buzz") + + def test_neither(self): + """Test numbers not divisible by 3 or 5""" + self.assertEqual(fizzbuzz(1), 1) + self.assertEqual(fizzbuzz(2), 2) + self.assertEqual(fizzbuzz(4), 4) + + +if __name__ == "__main__": + unittest.main() diff --git a/chatgpt-unit-tests-python/test_readers_pytest.py b/chatgpt-unit-tests-python/test_readers_pytest.py new file mode 100644 index 0000000000..e59f3d5b64 --- /dev/null +++ b/chatgpt-unit-tests-python/test_readers_pytest.py @@ -0,0 +1,38 @@ +import json + +import pytest + +# Assuming JSONReader is defined in 'your_module.py' +from readers import JSONReader + + +@pytest.fixture +def setup_json_file(tmp_path): + # Create a temporary JSON file + data = {"name": "John Doe", "age": 30} + file_path = tmp_path / "test_data.json" + with open(file_path, "w", encoding="utf-8") as file: + json.dump(data, file) + return file_path + + +def test_read_json_correctly(setup_json_file): + # Test that JSONReader reads the file correctly + reader = JSONReader(setup_json_file) + data = reader.read() + assert data == { + "name": "John Doe", + "age": 30, + }, "Should correctly read JSON content" + + +def test_file_not_found(): + # Test for handling of file not found exception + reader = JSONReader("non_existent_file.json") + with pytest.raises(FileNotFoundError): + reader.read() + + +# Additional tests can be added to cover more scenarios, +# such as reading empty files, +# files with invalid JSON content, etc. diff --git a/chatgpt-unit-tests-python/test_readers_unittest.py b/chatgpt-unit-tests-python/test_readers_unittest.py new file mode 100644 index 0000000000..3e7aca8e2e --- /dev/null +++ b/chatgpt-unit-tests-python/test_readers_unittest.py @@ -0,0 +1,35 @@ +import json +import os +import tempfile +import unittest + +from readers import JSONReader + + +class TestJSONReader(unittest.TestCase): + def setUp(self): + # Create a temporary file and write some JSON data to it + self.temp_file, self.temp_file_path = tempfile.mkstemp(suffix=".json") + self.test_data = {"name": "Test", "value": 123} + with os.fdopen(self.temp_file, "w", encoding="utf-8") as file: + json.dump(self.test_data, file) + + def tearDown(self): + # Clean up by removing the temporary file + os.remove(self.temp_file_path) + + def test_read_json(self): + # Test reading the JSON data + reader = JSONReader(self.temp_file_path) + data = reader.read() + self.assertEqual(data, self.test_data) + + def test_file_not_found(self): + # Test file not found error handling + reader = JSONReader("non_existent_file.json") + with self.assertRaises(FileNotFoundError): + _ = reader.read() + + +if __name__ == "__main__": + unittest.main()