Introduction
Writing tests is a critical skill for any developer aiming to ship reliable software. Yet, many teams struggle with test coverage due to time constraints or lack of experience. According to the 2023 Stack Overflow Developer Survey, 85% of respondents who write tests use unit testing frameworks like pytest, Jest, or unittest. However, crafting high-quality tests—especially edge cases and integration scenarios—remains a challenge.
This article provides 10 battle-tested prompts that you can feed into an AI assistant (like ChatGPT or Claude) to generate robust unit and integration tests. Each prompt includes a real-world example and code snippets to get you started immediately. Whether you're using Python's pytest, JavaScript's Jest, or Python's built-in unittest, these prompts cover the essentials.
1. Generate Unit Tests for a Pure Function
Prompt:
"Write unit tests using pytest for a Python function that calculates the factorial of a non-negative integer. Include tests for base cases, edge cases (e.g., n=0, n=1), typical inputs, and invalid inputs (e.g., negative numbers or floats). Use parametrize decorators."
Example Output:
import pytest
from math_utils import factorial
@pytest.mark.parametrize("input,expected", [
(0, 1),
(1, 1),
(5, 120),
(10, 3628800),
])
def test_factorial_valid(input, expected):
assert factorial(input) == expected
def test_factorial_negative():
with pytest.raises(ValueError):
factorial(-1)
def test_factorial_float():
with pytest.raises(TypeError):
factorial(2.5)
Why this works: The prompt forces the AI to consider parametrization, exception handling, and type validation—all best practices for unit testing.
2. Create Mock-Based Tests for External API Calls
Prompt:
"Write integration tests using Jest for a Node.js function that fetches user data from a REST API (https://api.example.com/users/:id). Mock the HTTP call using jest.fn() or a library like nock. Test successful response, 404 error, and network timeout. Use async/await."
Example Output:
const axios = require('axios');
const { getUser } = require('./userService');
jest.mock('axios');
describe('getUser', () => {
it('returns user data for valid id', async () => {
const userData = { id: 1, name: 'Alice' };
axios.get.mockResolvedValue({ data: userData });
const result = await getUser(1);
expect(result).toEqual(userData);
});
it('throws error for 404', async () => {
axios.get.mockRejectedValue(new Error('Not Found'));
await expect(getUser(999)).rejects.toThrow('Not Found');
});
it('handles timeout', async () => {
axios.get.mockRejectedValue(new Error('timeout'));
await expect(getUser(1)).rejects.toThrow('timeout');
});
});
Why this works: Mocking external dependencies is crucial for deterministic tests. The prompt explicitly asks for HTTP mocking and error scenarios.
3. Test Database Interactions with Fixtures
Prompt:
"Write integration tests using pytest and a SQLite in-memory database for a Python function that inserts a user into a 'users' table. Use pytest fixtures to set up the database schema and teardown. Include tests for successful insertion and duplicate email constraint."
Example Output:
import pytest
import sqlite3
from db import add_user
@pytest.fixture
def db_connection():
conn = sqlite3.connect(':memory:')
conn.execute('''CREATE TABLE users (id INTEGER PRIMARY KEY, email TEXT UNIQUE, name TEXT)''')
yield conn
conn.close()
def test_add_user_success(db_connection):
add_user(db_connection, 'alice@example.com', 'Alice')
cursor = db_connection.execute('SELECT * FROM users')
assert cursor.fetchone() == (1, 'alice@example.com', 'Alice')
def test_add_user_duplicate_email(db_connection):
add_user(db_connection, 'alice@example.com', 'Alice')
with pytest.raises(sqlite3.IntegrityError):
add_user(db_connection, 'alice@example.com', 'Bob')
Why this works: Fixtures ensure clean state per test. The prompt includes constraint validation, a common real-world scenario.
4. Generate Edge Case Tests for String Parsing
Prompt:
"Write unit tests using unittest for a function that parses a comma-separated string into a list of integers. Test empty string, single value, multiple values, whitespace handling, and invalid characters. Use setUp for common data."
Example Output:
import unittest
from parser import parse_csv
class TestParseCSV(unittest.TestCase):
def setUp(self):
self.parser = parse_csv
def test_empty_string(self):
self.assertEqual(self.parser(''), [])
def test_single_value(self):
self.assertEqual(self.parser('42'), [42])
def test_multiple_values(self):
self.assertEqual(self.parser('1,2,3'), [1, 2, 3])
def test_whitespace(self):
self.assertEqual(self.parser(' 1 , 2 '), [1, 2])
def test_invalid_string(self):
with self.assertRaises(ValueError):
self.parser('abc')
if __name__ == '__main__':
unittest.main()
Why this works: Edge cases (empty, whitespace) are often overlooked. The prompt explicitly asks for setUp to reduce boilerplate.
5. Test Asynchronous Code with pytest-asyncio
Prompt:
"Write unit tests using pytest and pytest-asyncio for an async function that fetches data from multiple URLs concurrently using asyncio.gather. Mock aiohttp.ClientSession. Test successful responses and partial failures."
Example Output:
import pytest
from aiohttp import ClientSession
from fetcher import fetch_all
@pytest.mark.asyncio
async def test_fetch_all_success(mocker):
mock_session = mocker.AsyncMock(spec=ClientSession)
mock_response = mocker.AsyncMock()
mock_response.json.return_value = {'key': 'value'}
mock_session.get.return_value.__aenter__.return_value = mock_response
result = await fetch_all(['url1', 'url2'], mock_session)
assert len(result) == 2
assert result[0] == {'key': 'value'}
Why this works: Async testing requires special setup. The prompt uses pytest-asyncio and mocker to handle asynchronous context managers.
6. Validate Test Coverage for a Module
Prompt:
"Generate a list of test cases for a Python class that handles file I/O (read, write, delete). Use pytest fixtures for temporary files. Include tests for file not found, permission errors, and empty file."
Example Output:
import pytest
import tempfile
import os
from file_handler import FileHandler
@pytest.fixture
def temp_dir():
with tempfile.TemporaryDirectory() as tmp:
yield tmp
def test_write_and_read(temp_dir):
handler = FileHandler(temp_dir)
handler.write('test.txt', 'content')
assert handler.read('test.txt') == 'content'
def test_file_not_found(temp_dir):
handler = FileHandler(temp_dir)
with pytest.raises(FileNotFoundError):
handler.read('nonexistent.txt')
Why this works: Temporary directories prevent side effects. The prompt ensures I/O error handling is tested.
7. Compare pytest, Jest, and unittest Syntax
Prompt:
"Write the same unit test (a function that adds two numbers) using pytest, Jest, and unittest. Highlight syntax differences: fixtures vs beforeEach, assert vs expect, parametrize vs test.each."
Example Output (pytest):
import pytest
from math_ops import add
def test_add():
assert add(2, 3) == 5
Example Output (Jest):
test('adds 2 + 3 to equal 5', () => {
expect(add(2, 3)).toBe(5);
});
Example Output (unittest):
import unittest
from math_ops import add
class TestAdd(unittest.TestCase):
def test_add(self):
self.assertEqual(add(2, 3), 5)
Why this works: This prompt is ideal for teams migrating between frameworks. It provides a side-by-side comparison.
8. Generate Integration Test for REST API
Prompt:
"Write integration tests for a Flask REST API endpoint POST /users that accepts JSON {name, email}. Use pytest and the test client. Test successful creation, missing fields, and duplicate email. Include status code and response body checks."
Example Output:
import pytest
from app import app
@pytest.fixture
def client():
app.config['TESTING'] = True
with app.test_client() as client:
yield client
def test_create_user_success(client):
response = client.post('/users', json={'name': 'Alice', 'email': 'alice@example.com'})
assert response.status_code == 201
assert response.json['name'] == 'Alice'
def test_missing_email(client):
response = client.post('/users', json={'name': 'Alice'})
assert response.status_code == 400
def test_duplicate_email(client):
client.post('/users', json={'name': 'Alice', 'email': 'alice@example.com'})
response = client.post('/users', json={'name': 'Bob', 'email': 'alice@example.com'})
assert response.status_code == 409
Why this works: Tests against a test client avoid network calls while still validating the full request-response cycle.
9. Handle Environment Variables in Tests
Prompt:
"Write unit tests using pytest for a function that reads a configuration value from environment variables. Mock os.environ to test default values and custom values. Use monkeypatch fixture."
Example Output:
import os
import pytest
from config import get_db_url
def test_default_value(monkeypatch):
monkeypatch.delenv('DB_URL', raising=False)
assert get_db_url() == 'sqlite:///default.db'
def test_custom_value(monkeypatch):
monkeypatch.setenv('DB_URL', 'postgres://user:pass@localhost/db')
assert get_db_url() == 'postgres://user:pass@localhost/db'
Why this works: Environment mocking prevents test coupling to the host machine. monkeypatch is a pytest built-in.
10. Test Performance with Timeout Assertions
Prompt:
"Write a performance test using pytest-timeout for a function that sorts a large list. Set a timeout of 2 seconds. Also test that the function raises an error for non-list input."
Example Output:
import pytest
from sorter import sort_large_list
@pytest.mark.timeout(2)
def test_sort_performance():
large_list = list(range(10000, 0, -1))
sorted_list = sort_large_list(large_list)
assert sorted_list == list(range(1, 10001))
def test_invalid_input():
with pytest.raises(TypeError):
sort_large_list('abc')
Why this works: Timeout guards against regressions that slow down code. The prompt combines performance and type validation.
Conclusion
Effective testing doesn't happen by accident—it requires intentional coverage of happy paths, edge cases, and failure modes. The prompts above give you a structured way to generate high-quality tests using AI, saving time while enforcing best practices. Start by adapting these prompts to your own codebase: pick one function, run the prompt, and review the output. Over time, you'll build a suite of reliable tests that catch bugs before they reach production.
For further reading, consult the official pytest documentation (https://docs.pytest.org/en/stable/), Jest docs (https://jestjs.io/docs/getting-started), and unittest docs (https://docs.python.org/3/library/unittest.html). Happy testing!
Comments