10 промтов для написания unit-тестов и интеграционных тестов: от pytest до Jest

10 промтов для написания unit-тестов и интеграционных тестов: от pytest до Jest

Введение

Тестирование — это не роскошь, а базовая дисциплина в современной разработке. По данным отчета State of Testing 2025, команды, которые пишут тесты до кода (TDD), сокращают количество багов в production на 40–60%. Однако написание качественных тестов отнимает время, которого вечно не хватает.

Современные языковые модели (LLM) умеют генерировать тесты не хуже джуниора, а иногда — и мидла. Главное — правильно составить промт. В этой подборке — 10 проверенных промтов, которые я использую ежедневно в работе с pytest (Python), Jest (JavaScript) и unittest (Python).

Каждый промт сопровождается реальным примером применения и результатом. Никакой воды — только рабочие конструкции.

1. Базовый unit-тест для функции с моками

Промт:

Напиши unit-тест на pytest для функции get_user_email(user_id), которая делает запрос к внешнему API. Используй unittest.mock для мока запроса. Проверь успешный ответ и случай, когда API возвращает 404.

Пример использования:

# Функция, которую тестируем
def get_user_email(user_id):
    response = requests.get(f"https://api.example.com/users/{user_id}")
    if response.status_code == 404:
        return None
    return response.json()["email"]

Результат генерации:

import pytest
from unittest.mock import patch
from my_module import get_user_email

@patch("my_module.requests.get")
def test_get_user_email_success(mock_get):
    mock_get.return_value.status_code = 200
    mock_get.return_value.json.return_value = {"email": "test@example.com"}
    assert get_user_email(1) == "test@example.com"

@patch("my_module.requests.get")
def test_get_user_email_not_found(mock_get):
    mock_get.return_value.status_code = 404
    assert get_user_email(999) is None

2. Интеграционный тест с базой данных

Промт:

Напиши интеграционный тест на pytest для функции create_order(user_id, items), которая сохраняет заказ в PostgreSQL через SQLAlchemy. Используй фикстуру с транзакцией, которая откатывается после теста. Проверь, что заказ создаётся с правильной суммой.

Пример использования:

# Функция, которую тестируем
def create_order(user_id, items, db_session):
    total = sum(item["price"] * item["quantity"] for item in items)
    order = Order(user_id=user_id, total=total, status="pending")
    db_session.add(order)
    db_session.commit()
    return order.id

Результат генерации:

import pytest
from my_app import create_order, Order

@pytest.fixture
def db_session():
    # Настройка тестовой БД
    session = get_test_session()
    yield session
    session.rollback()

def test_create_order_calculates_total(db_session):
    items = [{"price": 100, "quantity": 2}, {"price": 50, "quantity": 1}]
    order_id = create_order(1, items, db_session)
    order = db_session.query(Order).get(order_id)
    assert order.total == 250
    assert order.status == "pending"

3. Тест для асинхронного кода (pytest-asyncio)

Промт:

Напиши асинхронный тест на pytest с использованием pytest-asyncio для функции fetch_data(url), которая использует aiohttp. Проверь успешный ответ и таймаут.

Результат генерации:

import pytest
from unittest.mock import AsyncMock
from my_module import fetch_data

@pytest.mark.asyncio
async def test_fetch_data_success():
    mock_session = AsyncMock()
    mock_response = AsyncMock()
    mock_response.status = 200
    mock_response.json.return_value = {"key": "value"}
    mock_session.get.return_value.__aenter__.return_value = mock_response

    result = await fetch_data("http://test.com", mock_session)
    assert result == {"key": "value"}

@pytest.mark.asyncio
async def test_fetch_data_timeout():
    mock_session = AsyncMock()
    mock_session.get.side_effect = TimeoutError("Connection timed out")

    with pytest.raises(TimeoutError):
        await fetch_data("http://test.com", mock_session)

4. Jest-тест для React-компонента

Промт:

Напиши тест на Jest + React Testing Library для компонента UserProfile, который принимает userId и отображает имя пользователя, полученное через хук useFetchUser. Проверь состояния загрузки, успеха и ошибки.

Результат генерации:

import { render, screen, waitFor } from '@testing-library/react';
import UserProfile from './UserProfile';
jest.mock('./hooks/useFetchUser');

const mockUseFetchUser = require('./hooks/useFetchUser').useFetchUser;

test('shows loading state initially', () => {
  mockUseFetchUser.mockReturnValue({ user: null, loading: true, error: null });
  render(<UserProfile userId={1} />);
  expect(screen.getByText(/loading/i)).toBeInTheDocument();
});

test('displays user name on success', async () => {
  mockUseFetchUser.mockReturnValue({ user: { name: 'Alice' }, loading: false, error: null });
  render(<UserProfile userId={1} />);
  await waitFor(() => {
    expect(screen.getByText('Alice')).toBeInTheDocument();
  });
});

test('shows error message on failure', () => {
  mockUseFetchUser.mockReturnValue({ user: null, loading: false, error: 'Network error' });
  render(<UserProfile userId={1} />);
  expect(screen.getByText(/network error/i)).toBeInTheDocument();
});

5. Тест для исключений и краевых случаев

Промт:

Напиши тесты на pytest для функции divide(a, b), которая выбрасывает ValueError при делении на ноль и TypeError при нечисловых аргументах. Используй pytest.raises.

Результат генерации:

import pytest
from my_module import divide

def test_divide_normal():
    assert divide(10, 2) == 5.0

def test_divide_by_zero():
    with pytest.raises(ValueError, match="Cannot divide by zero"):
        divide(10, 0)

def test_divide_non_numeric():
    with pytest.raises(TypeError):
        divide("10", 2)

6. Параметризованные тесты (pytest.mark.parametrize)

Промт:

Перепиши тесты для функции calculate_discount(price, discount_percent) с использованием @pytest.mark.parametrize, чтобы покрыть граничные значения: 0%, 50%, 100% и отрицательные значения.

Результат генерации:

import pytest
from my_module import calculate_discount

@pytest.mark.parametrize("price, discount, expected", [
    (100, 0, 100),
    (200, 50, 100),
    (50, 100, 0),
    (100, -10, 110),  # отрицательная скидка = наценка
])
def test_calculate_discount(price, discount, expected):
    assert calculate_discount(price, discount) == expected

7. Тест для Flask/FastAPI эндпоинта

Промт:

Напиши тест на pytest для FastAPI эндпоинта POST /api/register, который принимает JSON с username и password, валидирует данные и возвращает токен. Используй TestClient.

Результат генерации:

from fastapi.testclient import TestClient
from my_app import app

client = TestClient(app)

def test_register_success():
    response = client.post("/api/register", json={"username": "testuser", "password": "strongpass123"})
    assert response.status_code == 200
    assert "token" in response.json()

def test_register_missing_field():
    response = client.post("/api/register", json={"username": "testuser"})
    assert response.status_code == 422

8. Тест для Celery-задачи

Промт:

Напиши тест для Celery-задачи send_welcome_email(user_email), которая отправляет email через SMTP. Используй pytest-celery или мок для send_email.

Результат генерации:

from unittest.mock import patch
from my_tasks import send_welcome_email

@patch("my_tasks.send_email")
def test_send_welcome_email(mock_send):
    send_welcome_email("test@example.com")
    mock_send.assert_called_once_with(
        to="test@example.com",
        subject="Welcome!",
        body="Thank you for registering"
    )

9. Тест для API с авторизацией (pytest + requests-mock)

Промт:

Напиши тест для функции get_orders(auth_token), которая делает GET-запрос к защищённому API. Используй requests-mock для симуляции ответа. Проверь успешный ответ и 401 Unauthorized.

Результат генерации:

import requests_mock
from my_module import get_orders

def test_get_orders_success():
    with requests_mock.Mocker() as m:
        m.get("https://api.example.com/orders", json=[{"id": 1}], status_code=200)
        result = get_orders("valid_token")
        assert result == [{"id": 1}]

def test_get_orders_unauthorized():
    with requests_mock.Mocker() as m:
        m.get("https://api.example.com/orders", status_code=401)
        result = get_orders("invalid_token")
        assert result is None

10. Генерация тестовой документации и покрытия

Промт:

Напиши скрипт на Python, который анализирует существующие тесты в папке tests/ и генерирует Markdown-отчёт с покрытием функций. Используй ast для парсинга исходного кода.

Результат генерации:

import ast
import os

def generate_coverage_report(test_dir="tests"):
report_lines = ["# Coverage Report\n", "

| Function | Tested |\n", "|---|---|\n"]
    for file in os.listdir(test_dir):
        if file.endswith("_test.py"):
            with open(os.path.join(test_dir, file)) as f:
                tree = ast.parse(f.read())
                for node in ast.walk(tree):
                    if isinstance(node, ast.FunctionDef):
report_lines.append(f"

| {node.name} | ✅ |\n")
    return "".join(report_lines)

Заключение

Промты — это не магия, а инструмент, который сокращает рутину. Вместо того чтобы писать 100 строк тестового кода вручную, вы тратите 30 секунд на формулировку запроса и получаете 80% готового решения. Остаётся только проверить и адаптировать под свой проект.

Главное правило: чем конкретнее промт, тем качественнее результат. Указывайте фреймворк, библиотеки для моков, ожидаемое поведение и краевые случаи. Тогда AI сгенерирует тесты, которые можно сразу запускать.

Попробуйте эти промты в своём проекте уже сегодня — и вы заметите, как скорость написания тестов вырастет в 2–3 раза. А если хотите углубиться в тестирование и автоматизацию, обратите внимание на практические курсы, где разбираются реальные кейсы из продакшена.

← Все статьи

Комментарии