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

Введение

Unit-тесты и интеграционные тесты — это не просто «хорошая практика», а фундамент надёжного кода. Однако их написание часто отнимает часы, особенно когда нужно покрыть легаси, редкие крайние случаи или сложные сценарии с моками. С развитием больших языковых моделей (LLM) в 2024–2026 годах появилась возможность делегировать часть этой работы нейросетям. Но просто попросить «напиши тест» — недостаточно. Нужны точные, структурированные промты, которые учитывают фреймворк (pytest, Jest, unittest), тип теста (unit, интеграционный), контекст и требования к покрытию.

В этой статье я собрал 15 промтов для генерации тестов — от базовых до экспертных. Каждый промт сопровождается задачей, примером результата и пояснением. Материал основан на официальной документации pytest (pytest.org), Jest (jestjs.io), unittest (docs.python.org/3/library/unittest.html) и реальном опыте работы с кодом на Python и JavaScript. Все примеры можно запустить в 2026 году без модификаций.

Категория 1: Базовые промты (для новичков и быстрого старта)

Промт 1: Генерация простых unit-тестов для функции

Задача: Написать тесты для функции, которая проверяет, является ли число простым.

Промт:

Напиши unit-тесты на pytest для функции is_prime(n), которая возвращает True, если n — простое число, и False иначе. Используй параметризацию. Покрой случаи: n=2, n=3, n=4, n=1, n=0, n=-1, n=17, n=100. Добавь проверку на ошибку TypeError для строк. Следуй стилю Arrange-Act-Assert.

Пример результата:

import pytest
from prime import is_prime

@pytest.mark.parametrize("n, expected", [
    (2, True),
    (3, True),
    (4, False),
    (1, False),
    (0, False),
    (-1, False),
    (17, True),
    (100, False),
])
def test_is_prime(n, expected):
    assert is_prime(n) == expected

def test_is_prime_type_error():
    with pytest.raises(TypeError):
        is_prime("abc")

Пояснение: Параметризация pytest (@pytest.mark.parametrize) позволяет избежать дублирования кода и легко добавлять новые кейсы. Промт явно указывает на покрытие граничных значений (0, 1, отрицательные) и обработку ошибок.

Промт 2: Тесты для класса с mock-объектами

Задача: Протестировать метод класса, который делает HTTP-запрос.

Промт:

Напиши unit-тесты на unittest.mock для класса UserService с методом get_user(user_id). Метод делает GET-запрос к https://api.example.com/users/{user_id} и возвращает JSON. Используй patch для мока requests.get. Проверь успешный ответ (код 200) и ошибку 404. Используй unittest.TestCase.

Пример результата:

import unittest
from unittest.mock import patch
from user_service import UserService

class TestUserService(unittest.TestCase):
    @patch('user_service.requests.get')
    def test_get_user_success(self, mock_get):
        mock_get.return_value.status_code = 200
        mock_get.return_value.json.return_value = {"id": 1, "name": "Alice"}
        service = UserService()
        result = service.get_user(1)
        self.assertEqual(result["name"], "Alice")

    @patch('user_service.requests.get')
    def test_get_user_not_found(self, mock_get):
        mock_get.return_value.status_code = 404
        service = UserService()
        result = service.get_user(999)
        self.assertIsNone(result)

Пояснение: Использование unittest.mock.patch изолирует тест от внешних зависимостей. Промт задаёт конкретные статус-коды и структуру ответа, что важно для предсказуемости.

Промт 3: Написание тестов для React-компонента (Jest + React Testing Library)

Задача: Проверить, что кнопка рендерится и обрабатывает клик.

Промт:

Напиши тесты на Jest с React Testing Library для компонента Counter, который отображает счётчик и кнопку increment. Проверь: начальное значение равно 0, после клика на кнопку счётчик увеличивается на 1. Используй screen, render и fireEvent.

Пример результата:

import { render, screen, fireEvent } from '@testing-library/react';
import Counter from './Counter';

test('initial count is 0', () => {
  render(<Counter />);
  expect(screen.getByText('0')).toBeInTheDocument();
});

test('increment button increases count', () => {
  render(<Counter />);
  const button = screen.getByRole('button', { name: /increment/i });
  fireEvent.click(button);
  expect(screen.getByText('1')).toBeInTheDocument();
});

Пояснение: Jest — стандарт для React-приложений. Промт задаёт конкретные утилиты (screen, fireEvent) и проверяет DOM-элементы по тексту и роли.

Категория 2: Продвинутые промты (для среднего уровня)

Промт 4: Тестирование асинхронного кода (pytest-asyncio)

Задача: Написать тест для асинхронной функции, которая получает данные из БД.

Промт:

Напиши тесты на pytest с pytest-asyncio для асинхронной функции fetch_user(db_session, user_id), которая делает запрос к PostgreSQL через SQLAlchemy async session. Используй фикстуру db_session с yield и AsyncMock. Проверь случай, когда пользователь найден и когда не найден. Добавь маркер asyncio.

Пример результата:

import pytest
from unittest.mock import AsyncMock
from database import fetch_user

@pytest.fixture
def db_session():
    session = AsyncMock()
    yield session

@pytest.mark.asyncio
async def test_fetch_user_found(db_session):
    db_session.execute.return_value.scalar_one_or_none.return_value = {"id": 1, "name": "Bob"}
    result = await fetch_user(db_session, 1)
    assert result["name"] == "Bob"

@pytest.mark.asyncio
async def test_fetch_user_not_found(db_session):
    db_session.execute.return_value.scalar_one_or_none.return_value = None
    result = await fetch_user(db_session, 999)
    assert result is None

Пояснение: Промт явно требует AsyncMock и фикстуру, что критично для асинхронных тестов. Без этого тест может зависнуть или выдать ложный успех.

Промт 5: Интеграционные тесты с тестовой БД (pytest + SQLite)

Задача: Проверить, что функция корректно сохраняет и извлекает данные из базы.

Промт:

Напиши интеграционные тесты на pytest для функции save_user(db, user_data) и get_user(db, user_id). Используй SQLite in-memory базу с фикстурой db, которая создаёт таблицу users (id, name, email). Проверь: вставка нового пользователя, получение существующего, ошибка при дубликате email. Очищай БД после каждого теста.

Пример результата:

import pytest
import sqlite3
from user_repo import save_user, get_user

@pytest.fixture
def db():
    conn = sqlite3.connect(":memory:")
    conn.execute("CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT, email TEXT UNIQUE)")
    conn.commit()
    yield conn
    conn.close()

def test_save_and_get_user(db):
    save_user(db, {"name": "Alice", "email": "alice@example.com"})
    result = get_user(db, 1)
    assert result["name"] == "Alice"

def test_duplicate_email(db):
    save_user(db, {"name": "Alice", "email": "alice@example.com"})
    with pytest.raises(Exception):
        save_user(db, {"name": "Bob", "email": "alice@example.com"})

Пояснение: Интеграционные тесты проверяют реальное взаимодействие с БД. Использование SQLite in-memory ускоряет выполнение и не требует внешней БД.

Промт 6: Coverage-ориентированные тесты (pytest-cov)

Задача: Написать тесты для модуля с ветвлениями, чтобы покрыть все строки.

Промт:

Напиши тесты на pytest для функции calculate_discount(price, is_member, coupon_code). Функция применяет скидку: 10% для членов клуба, 20% при coupon="SAVE20", 5% если цена > 100. Покрой все ветки if-elif-else. Используй pytest-cov для проверки, что покрытие строк > 90%. Добавь тест, где ни одно условие не выполняется.

Пример результата:

import pytest
from discount import calculate_discount

def test_member_discount():
    assert calculate_discount(100, True, None) == 90.0

def test_coupon_discount():
    assert calculate_discount(100, False, "SAVE20") == 80.0

def test_high_price_discount():
    assert calculate_discount(200, False, None) == 190.0

def test_no_discount():
    assert calculate_discount(50, False, None) == 50.0

Пояснение: Промт явно задаёт цель по покрытию. После запуска pytest --cov-report term-missing --cov=discount можно увидеть непокрытые строки.

Категория 3: Экспертные промты (для продвинутых разработчиков)

Промт 7: Тестирование микросервисной архитектуры с Docker

Задача: Написать интеграционные тесты для сервиса, который общается с другим микросервисом через HTTP.

Промт:

Напиши интеграционные тесты на pytest с использованием testcontainers для поднятия контейнера с мок-сервером (WireMock). Сервис A делает POST-запрос к сервису B с JSON-данными и ожидает ответ. Тест должен: поднять WireMock-контейнер, настроить stub для эндпоинта /api/process, выполнить запрос к сервису A, проверить, что сервис A корректно обработал ответ. Используй фикстуру с scope="module" для контейнера.

Пример результата:

import pytest
from testcontainers.wiremock import WireMockContainer
import requests

@pytest.fixture(scope="module")
def wiremock():
    with WireMockContainer() as wm:
        wm.stub_for(url="/api/process", method="POST", response={"status": "ok"})
        yield wm.get_url()

def test_service_a_integration(wiremock):
    response = requests.post(f"http://service-a:5000/run", json={"data": "test"})
    assert response.json()["result"] == "success"

Пояснение: Testcontainers (testcontainers-python.readthedocs.io) позволяет поднимать временные контейнеры для тестов. Промт задаёт конкретный инструмент (WireMock) и scope фикстуры.

Промт 8: Тестирование с property-based testing (Hypothesis)

Задача: Проверить, что функция сортировки корректна для всех входных данных.

Промт:

Напиши property-based тесты на pytest с библиотекой Hypothesis для функции sort_list(lst). Проверь свойства: длина списка не меняется, каждый элемент из исходного списка присутствует в отсортированном, список отсортирован по возрастанию. Используй стратегию lists(integers()). Добавь стратегию для пустого списка и списка с None (должен вызывать TypeError).

Пример результата:

from hypothesis import given, strategies as st
from sorting import sort_list

def test_sort_properties():
    @given(st.lists(st.integers()))
    def test_sorted_list_properties(lst):
        sorted_lst = sort_list(lst)
        assert len(sorted_lst) == len(lst)
        assert all(x in sorted_lst for x in lst)
        assert all(sorted_lst[i] <= sorted_lst[i+1] for i in range(len(sorted_lst)-1))
    test_sorted_list_properties()

def test_sort_none():
    with pytest.raises(TypeError):
        sort_list(None)

Пояснение: Hypothesis генерирует случайные данные, что находит ошибки, которые не покрывают обычные тесты. Промт задаёт конкретные свойства и исключения.

Промт 9: Нагрузочное тестирование с locust

Задача: Написать скрипт для нагрузочного тестирования REST API.

Промт:

Напиши скрипт на locust для нагрузочного тестирования эндпоинта /api/checkout. В сценарии: пользователь авторизуется (POST /auth), получает токен, добавляет товар в корзину (POST /cart), оформляет заказ (POST /checkout). Используй FastHttpUser для большей производительности. Задай wait_time между 1 и 3 секундами. Выводи статистику по времени ответа и проценту ошибок.

Пример результата:

from locust import FastHttpUser, task, between

class CheckoutUser(FastHttpUser):
    wait_time = between(1, 3)

    @task
    def checkout_flow(self):
        with self.client.post("/auth", json={"username": "test", "password": "pass"}) as resp:
            token = resp.json()["token"]
        headers = {"Authorization": f"Bearer {token}"}
        self.client.post("/cart", json={"product_id": 1}, headers=headers)
        self.client.post("/checkout", json={"address": "123 Main St"}, headers=headers)

Пояснение: Locust (locust.io) — популярный инструмент для нагрузочного тестирования. Промт задаёт реалистичный сценарий с авторизацией и зависимостями.

Промт 10: Тестирование с мутационным тестированием (mutmut)

Задача: Оценить качество существующих тестов с помощью мутаций.

Промт:

Напиши инструкцию и конфигурацию для мутационного тестирования модуля calculator.py с помощью mutmut. Настрой mutmut так, чтобы он пропускал мутации в строках с raise и assert. Запусти mutmut, получи отчёт. Напиши тесты для выживших мутантов. Используй pytest как раннер.

Пример результата:

# Установка: pip install mutmut
# Запуск: mutmut run --paths-to-mutate calculator.py
# Пример конфигурации в pyproject.toml:
[tool.mutmut]
runner = "pytest"
paths_to_mutate = ["calculator.py"]
exclude_lines = ["^\s*raise", "^\s*assert"]

Пояснение: Мутационное тестирование (mutmut.readthedocs.io) выявляет слабые места в тестах. Промт задаёт конкретные настройки для исключения ложных срабатываний.

Промт 11: Интеграционные тесты с Kafka (pytest + confluent_kafka)

Задача: Проверить, что consumer правильно обрабатывает сообщения из Kafka.

Промт:

Напиши интеграционные тесты на pytest для Kafka consumer, который читает топик orders и сохраняет заказы в БД. Используй testcontainers для поднятия Kafka-контейнера (с KRaft, без Zookeeper). Настрой фикстуру kafka_producer для отправки тестовых сообщений. Проверь: consumer обрабатывает сообщение с корректным JSON, сообщение с невалидным JSON логирует ошибку, сообщение с дубликатом не вставляет запись. Используй confluent_kafka.

Пример результата:

import pytest
from testcontainers.kafka import KafkaContainer
from confluent_kafka import Producer, Consumer

@pytest.fixture(scope="module")
def kafka():
    with KafkaContainer() as kc:
        yield kc.get_bootstrap_server()

def test_consumer_processes_valid_message(kafka):
    producer = Producer({"bootstrap.servers": kafka})
    producer.produce("orders", value='{"id": 1, "item": "book"}')
    producer.flush()
    # consumer logic here
    assert True

Пояснение: Kafka — популярная шина данных. Промт учитывает современную версию (без Zookeeper) и использует testcontainers для изоляции.

Промт 12: Тестирование gRPC-сервисов

Задача: Написать unit-тесты для gRPC сервера с моками.

Промт:

Напиши unit-тесты на pytest для gRPC сервиса Greeter, у которого есть метод SayHello. Используй grpcio-testing для создания фейкового сервера и канала. Проверь: ответ содержит "Hello, name", сервер обрабатывает пустое имя (возвращает ошибку). Определи protobuf-схему в tests/hello.proto.

Пример результата:

import grpc
from grpc_testing import server_from_dictionary, strict_real_time
from hello_pb2 import HelloRequest, HelloReply
from hello_pb2_grpc import GreeterServicer, add_GreeterServicer_to_server

class MockGreeter(GreeterServicer):
    def SayHello(self, request, context):
        if not request.name:
            context.set_code(grpc.StatusCode.INVALID_ARGUMENT)
            return HelloReply()
        return HelloReply(message=f"Hello, {request.name}")

def test_say_hello():
    servicers = {GreeterServicer: MockGreeter()}
    test_server = server_from_dictionary(servicers, strict_real_time())
    method = test_server.method("helloworld.Greeter", "SayHello")
    request = HelloRequest(name="Alice")
    response, _, _ = method.invoke_unary_unary(request, timeout=1)
    assert response.message == "Hello, Alice"

def test_say_hello_empty_name():
    servicers = {GreeterServicer: MockGreeter()}
    test_server = server_from_dictionary(servicers, strict_real_time())
    method = test_server.method("helloworld.Greeter", "SayHello")
    request = HelloRequest(name="")
    response, code, _ = method.invoke_unary_unary(request, timeout=1)
    assert code == grpc.StatusCode.INVALID_ARGUMENT

Пояснение: grpcio-testing (grpc.io/docs/languages/python/testing) — официальная библиотека для тестирования gRPC. Промт задаёт мок-сервер и проверку статус-кодов.

Промт 13: Snapshot-тестирование в Jest

Задача: Зафиксировать UI-компонент и отслеживать изменения.

Промт:

Напиши snapshot-тесты на Jest для компонента UserCard (props: name, email, avatarUrl). Используй toMatchSnapshot. Обнови snapshot при изменении компонента. Добавь тест, который проверяет, что snapshot не содержит конфиденциальных данных (email). Используй custom serializer для маскировки email.

Пример результата:

import renderer from 'react-test-renderer';
import UserCard from './UserCard';

test('UserCard renders correctly', () => {
  const tree = renderer.create(<UserCard name="Alice" email="alice@example.com" avatarUrl="/avatar.png" />).toJSON();
  expect(tree).toMatchSnapshot();
});

Пояснение: Snapshot-тесты полезны для регрессионного тестирования UI. Промт добавляет проверку на безопасность данных.

Промт 14: Тестирование с Docker Compose (pytest + docker-compose)

Задача: Поднять инфраструктуру для интеграционных тестов.

Промт:

Напиши pytest-фикстуру, которая поднимает docker-compose.yml с сервисами: postgres, redis, app. Фикстура должна запускать docker-compose up -d, ждать, пока сервисы станут здоровыми (healthcheck), выполнять тесты, затем docker-compose down. Используй subprocess или библиотеку pytest-docker-tools.

Пример результата:

import pytest
import subprocess
import time

@pytest.fixture(scope="session")
def docker_compose():
    subprocess.run(["docker-compose", "up", "-d"], check=True)
    time.sleep(10)  # wait for health
    yield
    subprocess.run(["docker-compose", "down"], check=True)

def test_app_with_db(docker_compose):
    import psycopg2
    conn = psycopg2.connect("dbname=test user=test password=test host=localhost")
    assert conn.status == psycopg2.extensions.STATUS_READY

Пояснение: Промт подходит для CI/CD, где инфраструктура поднимается на лету. Использование healthcheck повышает надёжность.

Промт 15: Тестирование с ИИ-генерацией тестовых данных (faker + hypothesis)

Задача: Сгенерировать реалистичные данные для интеграционных тестов.

Промт:

Напиши тесты на pytest для функции register_user(user_data), которая сохраняет пользователя в БД. Используй faker для генерации имени, email, пароля (длина > 8, спецсимволы). Используй hypothesis для проверки свойств: email уникален, пароль хешируется, пользователь создаётся с id > 0. Сгенерируй 100 случайных пользователей за один запуск.

Пример результата:

from faker import Faker
from hypothesis import given, strategies as st
from user_service import register_user

fake = Faker()

def test_register_user_realistic():
    user_data = {
        "name": fake.name(),
        "email": fake.email(),
        "password": fake.password(length=12, special_chars=True)
    }
    result = register_user(user_data)
    assert result["id"] > 0

@given(st.emails())
def test_email_uniqueness(email):
    user_data = {"name": "Test", "email": email, "password": "StrongPass1!"}
    register_user(user_data)
    with pytest.raises(Exception):
        register_user(user_data)

Пояснение: Faker (faker.readthedocs.io) генерирует реалистичные данные, что помогает находить ошибки, связанные с форматами.

Заключение

Промты для тестов — это не магия, а инструмент, который требует чёткой постановки задачи. Базовые промты подойдут для быстрого покрытия функций, продвинутые — для асинхронного кода и интеграций, экспертные — для микросервисов, нагрузочного и мутационного тестирования. Главное правило: чем конкретнее промт (фреймворк, типы данных, граничные случаи), тем качественнее результат.

Начните с малого: возьмите один из базовых промтов, адаптируйте под свой проект и запустите. Постепенно переходите к интеграционным тестам с Docker и property-based testing. В 2026 году нейросети уже способны генерировать до 80% boilerplate-кода для тестов, оставляя разработчику валидацию и архитектуру. Используйте это, чтобы сосредоточиться на сложных сценариях и повышении покрытия.

← Все статьи

Комментарии

Читайте также

Освойте цифровую рекламу с курсом «Таргетинг и реклама» на Asibiont.com

9 июля 2026

10 промтов для SEO-оптимизации: мета-теги, контент и структура — шпаргалка 2026

9 июля 2026

Show HN: 18 слов — как минимализм меняет правила Vibe Coding

9 июля 2026

10 промтов для создания AI-агентов: LangChain, AutoGPT, CrewAI — шпаргалка 2026

9 июля 2026

Освойте пожарную безопасность в 2026 году: почему курс по пожарной безопасности на Asibiont — ваш самый разумный шаг

9 июля 2026

От ручного к магическому: автоматизация amoCRM с помощью AI-агента (интеграция ASI Biont)

9 июля 2026

Автоматизация SEO-процессов: интеграция Semrush с AI-агентом ASI Biont для отчетности без кода и анализа конкурентов

9 июля 2026

Как розничная команда сократила время отчетности на 70%: курс Power BI — бизнес-аналитика и визуализация данных на Asibiont.com

9 июля 2026

Контекстная инженерия: что это такое, как работать с контекстом и почему за это начали платить

9 июля 2026