Edited prompt to forbid mocks or stubs during test generation

This commit is contained in:
renaud 2024-01-30 12:26:32 -08:00
parent c7eda167d5
commit e54b8db118
2 changed files with 114 additions and 93 deletions

View file

@ -130,7 +130,7 @@ async def regression_tests_from_function(
- Take advantage of the features of `{unit_test_package}` to make the tests easy to write and maintain
- Be easy to read and understand, with clean code and descriptive names
- Be deterministic, so that the tests always pass or fail in the same way
- It should not mock or stub out any dependencies, so that the tests are as close to the real world as possible
- It should not mock or stub any dependencies, so do not use pytest.mock or any other similar mocking or stubbing module, so that the testing environment is as close to the production environment as possible
To help unit test the function above, list diverse scenarios that the function should be able to handle (and under each scenario, include a few examples as sub-bullets).""",
}

View file

@ -11,8 +11,8 @@
"metadata": {
"collapsed": false,
"ExecuteTime": {
"end_time": "2024-01-30T01:24:49.328992Z",
"start_time": "2024-01-30T01:24:49.275573Z"
"end_time": "2024-01-30T19:32:00.691339Z",
"start_time": "2024-01-30T19:32:00.676001Z"
}
},
"id": "8d108492763a25a5",
@ -47,8 +47,8 @@
"metadata": {
"collapsed": false,
"ExecuteTime": {
"end_time": "2024-01-30T01:24:49.355646Z",
"start_time": "2024-01-30T01:24:49.331765Z"
"end_time": "2024-01-30T19:32:00.708815Z",
"start_time": "2024-01-30T19:32:00.695584Z"
}
},
"id": "694116ed54c4af6a",
@ -61,8 +61,8 @@
"metadata": {
"collapsed": true,
"ExecuteTime": {
"end_time": "2024-01-30T01:24:49.370274Z",
"start_time": "2024-01-30T01:24:49.355287Z"
"end_time": "2024-01-30T19:32:00.721388Z",
"start_time": "2024-01-30T19:32:00.713118Z"
}
},
"outputs": [],
@ -121,7 +121,7 @@
"- Take advantage of the features of `{unit_test_package}` to make the tests easy to write and maintain\n",
"- Be easy to read and understand, with clean code and descriptive names\n",
"- Be deterministic, so that the tests always pass or fail in the same way\n",
"- It should not mock or stub out any dependencies, so that the tests are as close to the real world as possible\n",
"- It should not mock or stub any dependencies, so do not use pytest.mock or any other similar mocking or stubbing module, so that the testing environment is as close to the production environment as possible\n",
"\n",
"To help unit test the function above, list diverse scenarios that the function should be able to handle (and under each scenario, include a few examples as sub-bullets).\"\"\",\n",
" }\n",
@ -272,8 +272,8 @@
"metadata": {
"collapsed": false,
"ExecuteTime": {
"end_time": "2024-01-30T01:24:49.370542Z",
"start_time": "2024-01-30T01:24:49.357646Z"
"end_time": "2024-01-30T19:32:00.724756Z",
"start_time": "2024-01-30T19:32:00.716228Z"
}
},
"id": "80fefa4a71d32347",
@ -315,13 +315,10 @@
"- Take advantage of the features of `pytest` to make the tests easy to write and maintain\n",
"- Be easy to read and understand, with clean code and descriptive names\n",
"- Be deterministic, so that the tests always pass or fail in the same way\n",
"- It should not mock or stub out any dependencies, so that the tests are as close to the real world as possible\n",
"- It should not mock or stub any dependencies, so do not use pytest.mock or any other similar mocking or stubbing module, so that the testing environment is as close to the production environment as possible\n",
"\n",
"To help unit test the function above, list diverse scenarios that the function should be able to handle (and under each scenario, include a few examples as sub-bullets).\n",
"\u001B[0m\n",
"[user]\n",
"In addition to those scenarios above, list a few rare or unexpected edge cases (and as before, under each edge case, include a few examples as sub-bullets).\n",
"\u001B[0m\n",
"[system]\n",
"You are a world-class Python developer with an eagle eye for unintended bugs and edge cases. You write careful, accurate unit tests. When asked to reply only with code, you write all of your code in a single block.\n",
"\u001B[0m\n",
@ -360,8 +357,8 @@
"metadata": {
"collapsed": false,
"ExecuteTime": {
"end_time": "2024-01-30T01:26:38.132968Z",
"start_time": "2024-01-30T01:24:49.364008Z"
"end_time": "2024-01-30T19:34:12.978425Z",
"start_time": "2024-01-30T19:32:00.721528Z"
}
},
"id": "3cb5881311ca16e2",
@ -377,9 +374,9 @@
"# imports\n",
"import pytest\n",
"import os\n",
"import subprocess\n",
"import logging\n",
"from unittest.mock import patch, mock_open\n",
"import subprocess\n",
"from tempfile import NamedTemporaryFile\n",
"\n",
"# function to test\n",
"def lint_code(path: str) -> str:\n",
@ -392,90 +389,114 @@
" logging.error(\"Failed to format\")\n",
" with open(path, \"r\") as f:\n",
" new_code = f.read()\n",
" return new_code\n",
"\n",
"# unit tests\n",
"\n",
"# Test valid file path with correct formatting\n",
"def test_lint_code_valid_file(tmp_path):\n",
" # Create a temporary Python file with content that needs formatting\n",
" test_file = tmp_path / \"test.py\"\n",
" test_file.write_text(\"def foo():\\n pass\")\n",
"# Test valid file path with Python code that needs formatting\n",
"def test_valid_file_needs_formatting():\n",
" with NamedTemporaryFile(\"w+\", suffix=\".py\", delete=False) as tmp:\n",
" tmp.write(\"def foo():\\n pass\\n\") # poorly formatted code\n",
" tmp_path = tmp.name\n",
" try:\n",
" lint_code(tmp_path)\n",
" with open(tmp_path, \"r\") as f:\n",
" content = f.read()\n",
" # Check that the code has been reformatted (e.g., proper indentation)\n",
" assert content == \"def foo():\\n pass\\n\"\n",
" finally:\n",
" os.remove(tmp_path)\n",
"\n",
" # Run lint_code function on the test file\n",
" lint_code(str(test_file))\n",
"# Test valid file path with Python code already formatted\n",
"def test_valid_file_already_formatted():\n",
" with NamedTemporaryFile(\"w+\", suffix=\".py\", delete=False) as tmp:\n",
" tmp.write(\"def foo():\\n pass\\n\") # already formatted code\n",
" tmp_path = tmp.name\n",
" try:\n",
" lint_code(tmp_path)\n",
" with open(tmp_path, \"r\") as f:\n",
" content = f.read()\n",
" # Check that the content is unchanged\n",
" assert content == \"def foo():\\n pass\\n\"\n",
" finally:\n",
" os.remove(tmp_path)\n",
"\n",
" # Read the file after linting\n",
" formatted_code = test_file.read_text()\n",
"\n",
" # Assert the code has been formatted (black adds an extra line break)\n",
" assert formatted_code == \"def foo():\\n pass\\n\"\n",
"\n",
"# Test non-existent file path\n",
"def test_lint_code_nonexistent_file():\n",
" # Define a file path that does not exist\n",
" fake_path = \"nonexistent_file.py\"\n",
"\n",
" # Assert that an AssertionError is raised when the file does not exist\n",
"# Test invalid file path\n",
"def test_invalid_file_path():\n",
" with pytest.raises(AssertionError):\n",
" lint_code(fake_path)\n",
" lint_code(\"/path/to/nonexistent/file.py\")\n",
"\n",
"# Test file path is a directory\n",
"def test_lint_code_directory_path(tmp_path):\n",
" # Use a temporary directory path instead of a file\n",
" directory_path = str(tmp_path)\n",
"\n",
" # Assert that an AssertionError is raised when the path is a directory\n",
"# Test file path to a directory\n",
"def test_file_path_to_directory(tmp_path):\n",
" dir_path = str(tmp_path)\n",
" with pytest.raises(AssertionError):\n",
" lint_code(directory_path)\n",
" lint_code(dir_path)\n",
"\n",
"# Test file with read permission issues\n",
"@patch(\"builtins.open\", new_callable=mock_open, read_data=\"def foo(): pass\")\n",
"def test_lint_code_read_permission_error(mock_file):\n",
" # Mock os.path.exists to return True\n",
" with patch(\"os.path.exists\", return_value=True):\n",
" # Mock the file open to raise a permission error\n",
" mock_file.side_effect = PermissionError\n",
"# Test file with read-only permissions\n",
"def test_read_only_file():\n",
" with NamedTemporaryFile(\"w+\", suffix=\".py\", delete=False) as tmp:\n",
" tmp.write(\"def foo():\\n pass\\n\")\n",
" tmp_path = tmp.name\n",
" os.chmod(tmp_path, 0o444) # read-only permissions\n",
" try:\n",
" with pytest.raises(subprocess.CalledProcessError):\n",
" lint_code(tmp_path)\n",
" finally:\n",
" os.chmod(tmp_path, 0o666) # reset permissions to allow deletion\n",
" os.remove(tmp_path)\n",
"\n",
" # Define a file path\n",
" file_path = \"test.py\"\n",
"# Test empty Python file\n",
"def test_empty_file():\n",
" with NamedTemporaryFile(\"w+\", suffix=\".py\", delete=False) as tmp:\n",
" tmp_path = tmp.name\n",
" try:\n",
" lint_code(tmp_path)\n",
" with open(tmp_path, \"r\") as f:\n",
" content = f.read()\n",
" # Check that the content is still empty\n",
" assert content == \"\"\n",
" finally:\n",
" os.remove(tmp_path)\n",
"\n",
" # Assert that a PermissionError is raised when the file is not readable\n",
" with pytest.raises(PermissionError):\n",
" lint_code(file_path)\n",
"# Test non-Python file\n",
"def test_non_python_file():\n",
" with NamedTemporaryFile(\"w+\", suffix=\".txt\", delete=False) as tmp:\n",
" tmp.write(\"This is not Python code.\")\n",
" tmp_path = tmp.name\n",
" try:\n",
" with pytest.raises(subprocess.CalledProcessError):\n",
" lint_code(tmp_path)\n",
" finally:\n",
" os.remove(tmp_path)\n",
"\n",
"# Test subprocess.run failure\n",
"@patch(\"subprocess.run\")\n",
"def test_lint_code_subprocess_failure(mock_run):\n",
" # Mock os.path.exists to return True\n",
" with patch(\"os.path.exists\", return_value=True):\n",
" # Mock subprocess.run to simulate a failure\n",
" mock_run.return_value.returncode = 1\n",
"# Test large Python file\n",
"def test_large_file():\n",
" large_content = \"def foo():\\n pass\\n\" * 1000 # large file with repeated content\n",
" with NamedTemporaryFile(\"w+\", suffix=\".py\", delete=False) as tmp:\n",
" tmp.write(large_content)\n",
" tmp_path = tmp.name\n",
" try:\n",
" lint_code(tmp_path)\n",
" with open(tmp_path, \"r\") as f:\n",
" content = f.read()\n",
" # Check that the content is properly formatted\n",
" assert content == large_content\n",
" finally:\n",
" os.remove(tmp_path)\n",
"\n",
" # Define a file path\n",
" file_path = \"test.py\"\n",
"\n",
" # Capture logging output\n",
" with pytest.raises(AssertionError):\n",
" lint_code(file_path)\n",
"\n",
"# Test subprocess.run success but with file read error\n",
"@patch(\"subprocess.run\")\n",
"def test_lint_code_subprocess_success_read_error(mock_run):\n",
" # Mock os.path.exists to return True\n",
" with patch(\"os.path.exists\", return_value=True):\n",
" # Mock subprocess.run to simulate success\n",
" mock_run.return_value.returncode = 0\n",
"\n",
" # Define a file path\n",
" file_path = \"test.py\"\n",
"\n",
" # Mock the file open to raise an IOError\n",
" with patch(\"builtins.open\", new_callable=mock_open, read_data=\"def foo(): pass\") as mock_file:\n",
" mock_file.side_effect = IOError\n",
"\n",
" # Assert that an IOError is raised when the file cannot be read after formatting\n",
" with pytest.raises(IOError):\n",
" lint_code(file_path)\n"
"# Test file path with special characters\n",
"def test_special_characters_in_file_path():\n",
" with NamedTemporaryFile(\"w+\", suffix=\".py\", prefix=\"test@#\", delete=False) as tmp:\n",
" tmp.write(\"def foo():\\n pass\\n\")\n",
" tmp_path = tmp.name\n",
" try:\n",
" lint_code(tmp_path)\n",
" with open(tmp_path, \"r\") as f:\n",
" content = f.read()\n",
" # Check that the code has been reformatted\n",
" assert content == \"def foo():\\n pass\\n\"\n",
" finally:\n",
" os.remove(tmp_path)\n"
]
}
],
@ -485,8 +506,8 @@
"metadata": {
"collapsed": false,
"ExecuteTime": {
"end_time": "2024-01-30T01:26:38.137668Z",
"start_time": "2024-01-30T01:26:38.132099Z"
"end_time": "2024-01-30T19:34:12.979917Z",
"start_time": "2024-01-30T19:34:12.973475Z"
}
},
"id": "639c96f42318a856",
@ -499,8 +520,8 @@
"metadata": {
"collapsed": false,
"ExecuteTime": {
"end_time": "2024-01-30T01:26:38.138721Z",
"start_time": "2024-01-30T01:26:38.135570Z"
"end_time": "2024-01-30T19:34:12.990244Z",
"start_time": "2024-01-30T19:34:12.979780Z"
}
},
"id": "12baa8a023eafc26",