15 промтов для написания unit-тестов и интеграционных тестов: шпаргалка для pytest и Jest
Тестирование — это не роскошь, а необходимость в современной разработке. Согласно отчету State of Testing Report 2023 от PractiTest, организации, внедрившие автоматизированное тестирование, сокращают время на регрессионное тестирование в среднем на 50-70%. Однако написание тестов вручную отнимает часы, особенно когда кодовая база растет. Здесь на помощь приходят промты — готовые инструкции для AI-генерации тестов. В этой подборке я собрал 15 конкретных промтов для pytest, Jest и unittest, которые можно скопировать и сразу использовать. Каждый промт сопровождается примером и пояснением, чтобы вы могли адаптировать его под свой проект.
1. Промт для базового unit-теста функции на Python (pytest)
Когда использовать: Когда нужно быстро покрыть тестами простую функцию, например, математическую операцию или обработчик строк.
Промт:
Напиши unit-тесты на pytest для функции calculate_discount(price, discount_percent), которая возвращает цену со скидкой. Используй фикстуры для подготовки данных и параметризацию для тестирования граничных случаев: discount_percent = 0, 10, 50, 100. Проверь, что функция выбрасывает ValueError для отрицательной скидки.
Пример использования:
import pytest
@pytest.fixture
def base_price():
return 1000
def calculate_discount(price, discount_percent):
if discount_percent < 0:
raise ValueError("Discount cannot be negative")
return price - (price * discount_percent / 100)
@pytest.mark.parametrize("price, discount, expected", [
(1000, 0, 1000),
(1000, 10, 900),
(1000, 50, 500),
(1000, 100, 0),
])
def test_calculate_discount(base_price, discount, expected):
assert calculate_discount(base_price, discount) == expected
def test_negative_discount():
with pytest.raises(ValueError):
calculate_discount(1000, -5)
Этот промт генерирует тесты с покрытием всех основных сценариев, включая ошибки.
2. Промт для тестирования класса с моками (unittest)
Когда использовать: Когда нужно изолировать тестируемый класс от внешних зависимостей, например, API или базы данных.
Промт:
Создай тесты на unittest для класса UserService с методом get_user(user_id), который вызывает внешний API через requests.get. Используй unittest.mock.patch для подмены requests.get. Проверь, что при статусе 200 возвращается словарь с данными, а при 404 — None. Добавь тест на выброс исключения при ошибке сети.
Пример использования:
import unittest
from unittest.mock import patch
import requests
class UserService:
def get_user(self, user_id):
response = requests.get(f"https://api.example.com/users/{user_id}")
if response.status_code == 200:
return response.json()
elif response.status_code == 404:
return None
raise ConnectionError("Network error")
class TestUserService(unittest.TestCase):
@patch('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, {"id": 1, "name": "Alice"})
@patch('requests.get')
def test_get_user_not_found(self, mock_get):
mock_get.return_value.status_code = 404
service = UserService()
result = service.get_user(1)
self.assertIsNone(result)
if __name__ == '__main__':
unittest.main()
Промт помогает избежать реальных вызовов API, ускоряя тесты.
3. Промт для интеграционного теста базы данных (pytest)
Когда использовать: Когда нужно проверить взаимодействие кода с реальной базой данных (например, SQLite) без использования моков.
Промт:
Напиши интеграционный тест на pytest для функции add_user_to_db(name, email), которая вставляет запись в таблицу users. Используй фикстуру с временной базой данных SQLite, создаваемой через tmp_path. Проверь, что запись добавляется, а дубликат email вызывает IntegrityError.
Пример использования:
import pytest
import sqlite3
def add_user_to_db(name, email, db_path):
conn = sqlite3.connect(db_path)
cursor = conn.cursor()
cursor.execute("INSERT INTO users (name, email) VALUES (?, ?)", (name, email))
conn.commit()
conn.close()
@pytest.fixture
def db_path(tmp_path):
path = tmp_path / "test.db"
conn = sqlite3.connect(path)
conn.execute("CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT, email TEXT UNIQUE)")
conn.close()
return path
def test_add_user_success(db_path):
add_user_to_db("Alice", "alice@example.com", db_path)
conn = sqlite3.connect(db_path)
cursor = conn.execute("SELECT * FROM users")
assert cursor.fetchone() == (1, "Alice", "alice@example.com")
conn.close()
def test_add_duplicate_email(db_path):
add_user_to_db("Alice", "alice@example.com", db_path)
with pytest.raises(sqlite3.IntegrityError):
add_user_to_db("Bob", "alice@example.com", db_path)
Этот тест проверяет реальное поведение базы данных, что важно для выявления ошибок целостности.
4. Промт для тестирования асинхронного кода (pytest-asyncio)
Когда использовать: Для тестирования async/await функций, например, в aiohttp или asyncio.
Промт:
Напиши асинхронные тесты на pytest с библиотекой pytest-asyncio для функции fetch_data(url), которая использует aiohttp.ClientSession для получения JSON. Используй фикстуру для создания сессии и мок aiohttp.ClientSession.get для возврата фиктивных данных.
Пример использования:
import pytest
from unittest.mock import AsyncMock, patch
import aiohttp
async def fetch_data(url, session):
async with session.get(url) as response:
return await response.json()
@pytest.mark.asyncio
async def test_fetch_data():
mock_response = AsyncMock()
mock_response.json.return_value = {"key": "value"}
mock_session = AsyncMock()
mock_session.get.return_value.__aenter__.return_value = mock_response
result = await fetch_data("http://test.com", mock_session)
assert result == {"key": "value"}
Промт помогает изолировать асинхронные вызовы, не создавая реальных HTTP-запросов.
5. Промт для тестирования исключений и краевых случаев (pytest)
Когда использовать: Когда нужно проверить, что функция корректно обрабатывает ошибки, пустые данные или граничные значения.
Промт:
Напиши тесты на pytest для функции divide(a, b), которая возвращает результат деления или выбрасывает ZeroDivisionError при b=0. Добавь параметризацию для b = 0, 1, -1, 0.001. Проверь, что при b=0 выбрасывается исключение, а при b=0.001 результат корректен.
Пример использования:
import pytest
def divide(a, b):
if b == 0:
raise ZeroDivisionError("division by zero")
return a / b
@pytest.mark.parametrize("a, b, expected", [
(10, 1, 10),
(10, -1, -10),
(10, 0.001, 10000),
])
def test_divide_success(a, b, expected):
assert divide(a, b) == expected
def test_divide_by_zero():
with pytest.raises(ZeroDivisionError):
divide(10, 0)
Этот подход покрывает не только успешные сценарии, но и ошибки.
6. Промт для тестов с фикстурами и conftest.py (pytest)
Когда использовать: Когда нужно переиспользовать сложные настройки (например, подключение к тестовой БД) между несколькими тестовыми файлами.
Промт:
Создай фикстуру в файле conftest.py для pytest, которая подготавливает экземпляр класса Database с таблицей items. В тесте используй эту фикстуру для проверки метода get_item(item_id). Фикстура должна быть scope='function', чтобы каждый тест начинался с чистого состояния.
Пример использования:
# conftest.py
import pytest
class Database:
def __init__(self):
self.data = {1: "item1", 2: "item2"}
def get_item(self, item_id):
return self.data.get(item_id)
@pytest.fixture(scope='function')
def db():
return Database()
# test_db.py
def test_get_item_existing(db):
assert db.get_item(1) == "item1"
def test_get_item_missing(db):
assert db.get_item(3) is None
Фикстуры делают тесты чище и уменьшают дублирование.
7. Промт для тестирования генераторов и итераторов (pytest)
Когда использовать: Для функций, возвращающих генераторы, например, при чтении больших файлов построчно.
Промт:
Напиши тесты на pytest для генератора read_lines(file_content), который принимает строку с переносами строк и возвращает каждую строку. Проверь, что генератор возвращает правильное количество строк и корректно обрабатывает пустой ввод.
Пример использования:
import pytest
def read_lines(content):
for line in content.split('\n'):
yield line
def test_read_lines_multiple():
content = "line1\nline2\nline3"
result = list(read_lines(content))
assert result == ["line1", "line2", "line3"]
def test_read_lines_empty():
content = ""
result = list(read_lines(content))
assert result == []
Тесты для генераторов важны, так как они часто используются в потоковой обработке.
8. Промт для тестов с параметризацией и комбинациями (pytest.mark.parametrize)
Когда использовать: Когда нужно проверить функцию на большом наборе входных данных, например, для валидации форм.
Промт:
Напиши параметризованные тесты на pytest для функции validate_email(email), которая проверяет, что email содержит @ и точку. Используй комбинацию из 10 тестовых случаев: валидные email, email без @, email без точки, пустая строка.
Пример использования:
import pytest
def validate_email(email):
return '@' in email and '.' in email
@pytest.mark.parametrize("email, expected", [
("user@example.com", True),
("user@example", False),
("userexample.com", False),
("", False),
("@example.com", True),
("user@.com", True),
])
def test_validate_email(email, expected):
assert validate_email(email) == expected
Параметризация позволяет покрыть много случаев без дублирования кода.
9. Промт для тестирования Middleware в веб-фреймворках (pytest)
Когда использовать: Для проверки промежуточных слоев в Flask или Django.
Промт:
Напиши тест на pytest для Flask middleware, который проверяет, что каждый ответ содержит заголовок X-Request-Id. Используй тестовый клиент Flask и добавь middleware через app.before_request и app.after_request.
Пример использования:
import pytest
from flask import Flask, request, g
app = Flask(__name__)
@app.before_request
def before_request():
g.request_id = request.headers.get('X-Request-Id', 'default')
@app.after_request
def after_request(response):
response.headers['X-Request-Id'] = g.request_id
return response
@app.route('/')
def index():
return 'OK'
@pytest.fixture
def client():
with app.test_client() as client:
yield client
def test_middleware_adds_header(client):
resp = client.get('/', headers={'X-Request-Id': '123'})
assert resp.headers.get('X-Request-Id') == '123'
def test_middleware_default(client):
resp = client.get('/')
assert resp.headers.get('X-Request-Id') == 'default'
Этот тест гарантирует, что middleware работает корректно в разных сценариях.
10. Промт для тестирования конфигураций и переменных окружения (pytest)
Когда использовать: Когда код зависит от переменных окружения, например, DATABASE_URL или API_KEY.
Промт:
Напиши тесты на pytest для функции get_config(key), которая читает значение из переменных окружения через os.environ. Используй monkeypatch для установки и сброса переменных. Проверь, что возвращается значение по умолчанию, если переменная не задана.
Пример использования:
import pytest
import os
def get_config(key, default=None):
return os.environ.get(key, default)
def test_get_config_exists(monkeypatch):
monkeypatch.setenv('DATABASE_URL', 'postgres://localhost')
assert get_config('DATABASE_URL') == 'postgres://localhost'
def test_get_config_default(monkeypatch):
monkeypatch.delenv('DATABASE_URL', raising=False)
assert get_config('DATABASE_URL', 'sqlite:///test.db') == 'sqlite:///test.db'
Monkeypatch — мощный инструмент для изоляции тестов от окружения.
11. Промт для тестирования производительности (pytest-benchmark)
Когда использовать: Когда нужно убедиться, что функция работает достаточно быстро, например, в критических участках кода.
Промт:
Напиши тест производительности на pytest с библиотекой pytest-benchmark для функции sort_list(data), которая сортирует список из 1000 элементов. Установи порог времени выполнения в 0.01 секунды.
Пример использования:
import pytest
def sort_list(data):
return sorted(data)
def test_sort_performance(benchmark):
data = list(range(1000, 0, -1))
result = benchmark(sort_list, data)
assert result == list(range(1, 1001))
Бенчмарки помогают отслеживать деградацию производительности.
12. Промт для тестирования HTTP-запросов (responses library)
Когда использовать: Для мокирования HTTP-запросов без реального соединения.
Промт:
Напиши тест на pytest с библиотекой responses для функции fetch_user(user_id), которая делает GET-запрос к https://api.example.com/users/{user_id}. Используй декоратор responses.activate для подмены ответа. Проверь, что возвращается JSON с данными.
Пример использования:
import pytest
import responses
import requests
def fetch_user(user_id):
response = requests.get(f"https://api.example.com/users/{user_id}")
return response.json()
@responses.activate
def test_fetch_user():
responses.add(
responses.GET,
"https://api.example.com/users/1",
json={"id": 1, "name": "Alice"},
status=200
)
result = fetch_user(1)
assert result == {"id": 1, "name": "Alice"}
Библиотека responses упрощает тестирование внешних API.
13. Промт для тестирования декораторов (pytest)
Когда использовать: Когда нужно проверить, что декоратор правильно модифицирует поведение функции.
Промт:
Напиши тест на pytest для декоратора log_calls, который выводит в лог имя функции и аргументы. Используй фикстуру caplog для захвата логов. Проверь, что лог содержит имя функции и аргументы.
Пример использования:
import pytest
import logging
def log_calls(func):
def wrapper(*args, **kwargs):
logging.info(f"Calling {func.__name__} with args={args}, kwargs={kwargs}")
return func(*args, **kwargs)
return wrapper
@log_calls
def add(a, b):
return a + b
def test_log_calls(caplog):
caplog.set_level(logging.INFO)
result = add(2, 3)
assert result == 5
assert "Calling add with args=(2, 3), kwargs={}" in caplog.text
Тесты для декораторов важны, так как они могут влиять на логику приложения.
14. Промт для тестирования файлового ввода-вывода (pytest)
Когда использовать: Для функций, работающих с файлами: чтение, запись, обработка CSV или JSON.
Промт:
Напиши тест на pytest для функции save_data_to_json(data, file_path), которая сохраняет словарь в JSON-файл. Используй фикстуру tmp_path для создания временного файла. Проверь, что файл создается и содержит правильные данные.
Пример использования:
import pytest
import json
def save_data_to_json(data, file_path):
with open(file_path, 'w') as f:
json.dump(data, f)
def test_save_data_to_json(tmp_path):
data = {"name": "Alice", "age": 30}
file_path = tmp_path / "data.json"
save_data_to_json(data, file_path)
with open(file_path, 'r') as f:
loaded = json.load(f)
assert loaded == data
tmp_path обеспечивает изоляцию и автоматическую очистку.
15. Промт для тестирования API с помощью pytest и Flask (интеграционные)
Когда использовать: Для интеграционного тестирования REST API, созданного на Flask.
Промт:
Напиши интеграционный тест на pytest для Flask-приложения с эндпоинтом POST /users, который принимает JSON с name и email. Используй тестовый клиент. Проверь, что при успешном создании возвращается статус 201 и JSON с id, а при отсутствии email — 400.
Пример использования:
import pytest
from flask import Flask, request, jsonify
app = Flask(__name__)
users_db = []
@app.route('/users', methods=['POST'])
def create_user():
data = request.get_json()
if not data or 'email' not in data:
return jsonify({'error': 'Email is required'}), 400
user = {'id': len(users_db) + 1, 'name': data.get('name'), 'email': data['email']}
users_db.append(user)
return jsonify(user), 201
@pytest.fixture
def client():
with app.test_client() as client:
yield client
def test_create_user_success(client):
resp = client.post('/users', json={'name': 'Alice', 'email': 'alice@example.com'})
assert resp.status_code == 201
assert resp.get_json()['id'] == 1
def test_create_user_missing_email(client):
resp = client.post('/users', json={'name': 'Bob'})
assert resp.status_code == 400
assert resp.get_json()['error'] == 'Email is required'
Интеграционные тесты проверяют полный цикл запроса и ответа.
Заключение
Эти 15 промтов покрывают большинство сценариев тестирования, с которыми сталкивается разработчик: от простых unit-тестов до интеграционных тестов с базами данных и API. Копируйте их, адаптируйте под свои проекты и экономьте время. Начните с первого промта и постепенно внедряйте остальные — ваша кодовая база станет надежнее, а регрессионные ошибки уйдут в прошлое. Если вы хотите углубиться в тему, рекомендую изучить официальную документацию pytest (https://docs.pytest.org) и Jest (https://jestjs.io/docs). Тестируйте с умом!
Комментарии