Автоматизация тестирования — одна из главных задач разработчика. Современные AI-ассистенты (GPT-4, Claude, Copilot) умеют генерировать качественные тесты, если дать правильный промт. В этой подборке — 14 готовых промтов для unit- и интеграционных тестов на pytest, Jest и unittest. Каждый промт сопровождается примером кода и пояснением, как его адаптировать под ваш проект.
Общие промты для генерации тестов
1. Базовый unit-тест для функции
Для какой задачи: Быстро написать тест для конкретной функции с типовыми сценариями.
Промт: "Напиши unit-тест на pytest для функции {название} из модуля {модуль}. Учти: валидные входные данные, граничные случаи (пустая строка, None, отрицательные числа) и ожидаемые исключения. Используй фикстуры pytest для подготовки данных."
Пример: Функция divide(a, b):
import pytest
from calc import divide
def test_divide_normal():
assert divide(10, 2) == 5.0
def test_divide_by_zero():
with pytest.raises(ZeroDivisionError):
divide(5, 0)
def test_divide_negative():
assert divide(-6, 3) == -2.0
Совет: Промт можно дополнить требованием coverage > 80%.
2. Тест с использованием mock
Для какой задачи: Изолировать тестируемый модуль от внешних зависимостей (БД, API).
Промт: "Создай pytest-тест для функции get_user_name(user_id), которая вызывает внешний API (через requests.get). Замокай вызов requests.get с помощью unittest.mock.patch. Проверь: успешный ответ, ответ с ошибкой 404, таймаут."
Пример:
from unittest.mock import patch
import pytest
from user_service import get_user_name
@patch('user_service.requests.get')
def test_get_user_name_success(mock_get):
mock_get.return_value.status_code = 200
mock_get.return_value.json.return_value = {'name': 'Alice'}
assert get_user_name(1) == 'Alice'
@patch('user_service.requests.get')
def test_get_user_name_not_found(mock_get):
mock_get.return_value.status_code = 404
assert get_user_name(99) is None
Совет: Используй фикстуры mocker из pytest-mock для более короткого синтаксиса.
3. Параметризованные тесты
Для какой задачи: Перебор множества входных данных без дублирования кода.
Промт: "Напиши параметризованный тест на pytest для функции calculate_discount(price, discount). Проверь: 0%, 10%, 50%, 100%, отрицательная скидка (должна вызывать ValueError). Используй @pytest.mark.parametrize."
Пример:
import pytest
from shop import calculate_discount
@pytest.mark.parametrize("price,discount,expected", [
(100, 0, 100),
(200, 10, 180),
(50, 50, 25),
(30, 100, 0),
])
def test_calculate_discount_valid(price, discount, expected):
assert calculate_discount(price, discount) == expected
@pytest.mark.parametrize("price,discount", [(50, -10), (100, 120)])
def test_calculate_discount_invalid(price, discount):
with pytest.raises(ValueError):
calculate_discount(price, discount)
Совет: Группируй тесты по категориям с помощью pytest.mark.
4. Тесты для асинхронного кода
Для какой задачи: Тестирование async/await функций.
Промт: "Напиши тест на pytest для асинхронной функции fetch_data(url), используя pytest-asyncio. Промокай HTTP-клиент (aiohttp.ClientSession). Проверь успешный запрос и ошибку соединения."
Пример:
import pytest
from unittest.mock import AsyncMock, patch
from fetcher import fetch_data
@pytest.mark.asyncio
@patch('fetcher.aiohttp.ClientSession.get')
async def test_fetch_data_success(mock_get):
mock_response = AsyncMock()
mock_response.status = 200
mock_response.json.return_value = {'key': 'value'}
mock_get.return_value.__aenter__.return_value = mock_response
data = await fetch_data('http://example.com/api')
assert data == {'key': 'value'}
Совет: Установи pytest-asyncio и добавь asyncio_mode = auto в pytest.ini.
Промты для интеграционных тестов
5. Интеграционный тест REST API (pytest + requests)
Для какой задачи: Проверить взаимодействие с реальным API (или тестовым контейнером).
Промт: "Напиши интеграционный тест для эндпоинта POST /api/users с телом {"name": "...", "email": "..."}. Проверь: статус 201, заголовок Location, содержимое ответа. Используй requests и фикстуру base_url."
Пример:
import requests
import pytest
@pytest.fixture
def base_url():
return "http://localhost:8000/api"
def test_create_user(base_url):
payload = {"name": "Bob", "email": "bob@example.com"}
response = requests.post(f"{base_url}/users", json=payload)
assert response.status_code == 201
assert "id" in response.json()
assert response.headers.get("location") is not None
@pytest.mark.integration
def test_get_nonexistent_user(base_url):
response = requests.get(f"{base_url}/users/99999")
assert response.status_code == 404
Совет: Помечай интеграционные тесты маркером @pytest.mark.integration и отключай их в CI при unit-прогоне (с помощью -m "not integration").
6. Тест с testcontainers (БД)
Для какой задачи: Интеграционное тестирование с реальной PostgreSQL в Docker-контейнере.
Промт: "Напиши тест с использованием testcontainers-pytest. Запусти контейнер PostgreSQL, выполни миграции (SQLAlchemy), создай запись и проверь её чтение. Удали контейнер после теста."
Пример:
import pytest
from testcontainers.postgres import PostgresContainer
from sqlalchemy import create_engine, text
@pytest.fixture(scope="session")
def postgres_container():
with PostgresContainer("postgres:15") as postgres:
yield postgres
def test_database_operations(postgres_container):
engine = create_engine(postgres_container.get_connection_url())
with engine.connect() as conn:
conn.execute(text("CREATE TABLE users (id SERIAL PRIMARY KEY, name VARCHAR(255))"))
conn.execute(text("INSERT INTO users (name) VALUES ('Alice')"))
result = conn.execute(text("SELECT name FROM users")).fetchone()
assert result[0] == "Alice"
Совет: Используй scope="session" для контейнера, чтобы не пересоздавать его на каждый тест.
7. Тест на Jest для React-компонента
Для какой задачи: Unit-тестирование UI-компонентов с помощью Jest и React Testing Library.
Промт: "Напиши тест на Jest для компонента Button (props: label, onClick, disabled). Проверь: рендеринг текста, вызов onClick при клике, отсутствие вызова при disabled. Используй @testing-library/react."
Пример:
import { render, screen, fireEvent } from '@testing-library/react';
import Button from './Button';
test('renders label and handles click', () => {
const handleClick = jest.fn();
render(<Button label="Submit" onClick={handleClick} />);
expect(screen.getByText('Submit')).toBeInTheDocument();
fireEvent.click(screen.getByText('Submit'));
expect(handleClick).toHaveBeenCalledTimes(1);
});
test('does not fire click when disabled', () => {
const handleClick = jest.fn();
render(<Button label="Submit" onClick={handleClick} disabled />);
fireEvent.click(screen.getByText('Submit'));
expect(handleClick).not.toHaveBeenCalled();
});
Совет: Для сложных компонентов используй userEvent из @testing-library/user-event для имитации реальных действий пользователя.
8. Тест на Jest для асинхронного API-клиента
Для какой задачи: Тестирование асинхронных вызовов в Node.js.
Промт: "Напиши Jest-тест для функции getUser(id), которая делает fetch. Замокай global.fetch с помощью jest.spyOn. Проверь: успешный ответ (200), ошибку 500, reject при network error."
Пример:
import { getUser } from './userService';
beforeEach(() => {
jest.restoreAllMocks();
});
test('fetches user successfully', async () => {
jest.spyOn(global, 'fetch').mockResolvedValueOnce({
ok: true,
json: async () => ({ id: 1, name: 'Alice' }),
});
const user = await getUser(1);
expect(user).toEqual({ id: 1, name: 'Alice' });
});
test('throws on non-ok response', async () => {
jest.spyOn(global, 'fetch').mockResolvedValueOnce({ ok: false, status: 500 });
await expect(getUser(2)).rejects.toThrow('HTTP error 500');
});
Совет: Используй jest.mock('module') для глобального мока модулей.
9. Промт для unittest (Python stdlib)
Для какой задачи: Если проект использует встроенный unittest вместо pytest.
Промт: "Напиши тест в стиле unittest.TestCase для класса Calculator с методами add, subtract, multiply, divide. Используй setUp для создания экземпляра, добавь тест для деления на ноль с assertRaises."
Пример:
import unittest
from calc import Calculator
class TestCalculator(unittest.TestCase):
def setUp(self):
self.calc = Calculator()
def test_add(self):
self.assertEqual(self.calc.add(2, 3), 5)
def test_divide_by_zero(self):
with self.assertRaises(ZeroDivisionError):
self.calc.divide(10, 0)
def test_subtract_negative(self):
self.assertEqual(self.calc.subtract(0, 5), -5)
if __name__ == '__main__':
unittest.main()
Совет: Можно использовать pytest для запуска unittest-тестов — работает без изменений.
10. Тест покрытия граничных случаев (edge cases)
Для какой задачи: Проверить неочевидные сценарии: пустые списки, NaN, переполнение.
Промт: "Напиши тест для функции process_numbers(nums), которая возвращает сумму и среднее. Включи: пустой список (вызов ValueError), список с одним элементом, список с float('inf'), список с отрицательными нулями. Используй pytest.approx для float."
Пример:
import pytest
from stats import process_numbers
def test_empty_list():
with pytest.raises(ValueError):
process_numbers([])
def test_single_element():
result = process_numbers([42])
assert result == (42, 42.0)
def test_infinity():
result = process_numbers([1, float('inf')])
assert result[1] == pytest.approx(float('inf'))
Совет: Используй таблицу решений для перебора комбинаций.
11. Тест производительности (pytest-benchmark)
Для какой задачи: Проверка, что функция не деградировала по скорости.
Промт: "Напиши бенчмарк для функции sort_list(data) с помощью pytest-benchmark. Используй параметры: список из 1000 чисел, список строк, список с дубликатами. Установи пороговое время в 0.1 секунды."
Пример:
import pytest
from utils import sort_list
def test_sort_performance(benchmark):
data = list(range(1000, 0, -1))
result = benchmark(sort_list, data)
assert result == list(range(1, 1001))
Совет: Добавь --benchmark-columns=min,avg,max для детализации.
12. Промт для генерации тест-репорта (coverage)
Для какой задачи: Быстро создать тесты для файла с низким покрытием.
Промт: "Посмотри на файл {path} с покрытием 40%. Напиши тесты для всех непокрытых строк. Учти, что в файле есть условные операторы, циклы и обработка исключений. Используй pytest."
Пример: (без кода, поскольку зависит от анализа) — AI сам определит непокрытые строки, если предоставить код.
Совет: Сначала запусти pytest-cov, чтобы получить XML-отчёт, а затем передай его AI.
13. Тест для конфигураций (environment variables)
Для какой задачи: Проверка, что приложение корректно читает переменные окружения.
Промт: "С помощью monkeypatch в pytest напиши тест для функции get_db_url(), которая читает DATABASE_URL из os.environ. Проверь: установлена переменная, не установлена (должен быть fallback), пустая строка."
Пример:
import os
import pytest
from config import get_db_url
def test_db_url_custom(monkeypatch):
monkeypatch.setenv('DATABASE_URL', 'postgres://localhost/mydb')
assert get_db_url() == 'postgres://localhost/mydb'
def test_db_url_fallback(monkeypatch):
monkeypatch.delenv('DATABASE_URL', raising=False)
assert get_db_url() == 'sqlite:///default.db'
Совет: Используй monkeypatch.setattr для мока сложных зависимостей.
14. Интеграционный тест message broker (Redis/Kafka)
Для какой задачи: Проверка publish/subscribe в тестовом контейнере.
Промт: "Напиши тест с testcontainers для приложения, которое слушает сообщения из Redis Pub/Sub. Отправь сообщение через Redis-клиент, дождись обработки, проверь результат в БД."
Пример:
import pytest
from testcontainers.redis import RedisContainer
from app import MessageHandler
@pytest.mark.integration
def test_redis_message_handling():
with RedisContainer("redis:7") as redis:
handler = MessageHandler(redis.get_connection_url())
handler.start_listening()
# publish message via low-level client
import redis as r
client = r.Redis.from_url(redis.get_connection_url())
client.publish('events', '{"action": "test"}')
# wait and assert some side effect
# ... (specific to app logic)
assert True
Совет: Для тестирования Kafka используй testcontainers-kafka.
Заключение
Правильно составленный промт сокращает время написания тестов в 3–5 раз. Главное — явно указывать каркас: названия фикстур, типы моков, ожидаемые исключения. Комбинируйте эти шаблоны со своей предметной областью — и вы получите стабильный набор тестов, понятный коллегам. Помните, что AI-сгенерированные тесты стоит запускать в CI и проверять покрытие; они не отменяют ручного code review, но превращают рутину в пару строк промта.
Комментарии