Промпт: тесты к функции
Набор юнит-тестов с крайними случаями. Готовый промт на русском: скопируйте, подставьте свои данные и вставьте в GigaChat, YandexGPT, ChatGPT, Claude или Gemini.
Текст промпта
Что подставить в промт
| Поле | Пример |
|---|---|
| {framework} | pytest |
| {code} | def discount(price, percent): return price - price * percent / 100 |
Ответы нейросетей на этот промпт
Тестирование функции discount
Вот набор тестов для функции discount, покрывающий типичные сценарии, граничные условия, неправильный ввод и потенциальные ошибки.
import pytest
# Базовый случай проверки скидки
def test_discount_basic():
result = discount(100, 50)
assert result == 50
# Проверка нулевой цены и процента
def test_discount_zero_price_and_percent():
result = discount(0, 0)
assert result == 0
# Цена равна нулю, процент положительный
def test_discount_zero_price_positive_percent():
result = discount(0, 20)
assert result == 0
# Положительная цена, процент равен нулю
def test_discount_positive_price_zero_percent():
result = discount(100, 0)
assert result == 100
# Максимальная допустимая цена Python float (по сути бесконечность)
@pytest.mark.xfail(reason="Infinity input not handled correctly")
def test_discount_maximum_value():
max_float = float('inf')
result = discount(max_float, 50)
# Ожидается, что результат будет также inf, но здесь возможна ошибка реализации
assert result == max_float / 2
# Граница — максимальная положительная цена и максимальный процент
def test_discount_max_positive_values():
max_int = 9_223_372_036_854_775_807 # Max int value in most systems
result = discount(max_int, 100)
assert result == 0
# Отрицательная цена и отрицательный процент
def test_discount_negative_input():
result = discount(-100, -50)
assert result == -150
# Недопустимый входной параметр (не число)
@pytest.mark.parametrize("price,percent", [
("string", 50),
(100, "fifty"),
])
def test_discount_invalid_type(price, percent):
with pytest.raises(TypeError):
discount(price, percent)
# Необработанная ситуация деления на ноль (процент = 100%)
def test_discount_divide_by_zero():
# Функция корректно обрабатывает этот случай,
# поскольку вычисление происходит через умножение,
# однако стоит проверить такое поведение явно
result = discount(100, 100)
assert result == 0
# Неправильный процент больше 100%
def test_discount_over_100_percent():
result = discount(100, 150)
assert result == -50
# Ситуация, когда скидка превышает цену товара
def test_discount_exceeds_price():
result = discount(50, 200)
assert result == -50
# Пограничное значение для процента (точность округления)
def test_discount_rounding_edge_case():
result = discount(100, 99.99999999999999)
# В зависимости от платформы точность вычислений может варьироваться,
# нужно проверять возможные варианты результата
assert abs(result - 0.00000000000001) < 1e-15
Особенности поведения функции:
- Деление на ноль: Функция ведет себя правильно даже при значении процента равному 100%, поскольку деление на 100 выполняется после вычитания (умножением). Таким образом, проверка деления на ноль не нужна.
- Отрицательные значения: Допускается использование отрицательных цен и процентов, что может привести к нестандартным результатам, таким как получение отрицательной итоговой стоимости (
-50при цене100и скидке150%).
- Границы точности чисел с плавающей точкой: Использование больших значений типа float может вызвать проблемы с точностью, особенно при приближенных расчетах, связанных с дробями.
Таким образом, эти тесты охватывают основные рабочие ситуации, граничный контроль и необычные входные данные.
Ниже пример тестов для pytest.
Предположим, функция лежит в файле discount.py:
# discount.py
def discount(price, percent):
return price - price * percent / 100
Тесты:
# test_discount.py
import pytest
from discount import discount
@pytest.mark.parametrize(
"price, percent, expected",
[
(100, 10, 90),
(200, 25, 150),
(999, 15, 849.15),
(1000, 12.5, 875),
],
)
def test_discount_обычные_случаи(price, percent, expected):
assert discount(price, percent) == pytest.approx(expected)
@pytest.mark.parametrize(
"price, percent, expected",
[
(0, 10, 0),
(100, 0, 100),
(100, 100, 0),
(0, 0, 0),
(0, 100, 0),
],
)
def test_discount_граничные_значения(price, percent, expected):
assert discount(price, percent) == pytest.approx(expected)
def test_discount_очень_большая_цена():
assert discount(10**12, 10) == pytest.approx(900_000_000_000)
@pytest.mark.parametrize(
"price, percent",
[
(None, 10),
(100, None),
("100", 10),
(100, "10"),
("", 10),
(100, ""),
([100], 10),
(100, [10]),
({}, 10),
(100, {}),
],
)
def test_discount_неверный_тип_данных_вызывает_type_error(price, percent):
with pytest.raises(TypeError):
discount(price, percent)
@pytest.mark.xfail(reason="Функция не валидирует отрицательную цену")
def test_discount_отрицательная_цена_должна_быть_ошибкой():
with pytest.raises(ValueError):
discount(-100, 10)
@pytest.mark.xfail(reason="Функция не валидирует отрицательный процент скидки")
def test_discount_отрицательный_процент_должен_быть_ошибкой():
with pytest.raises(ValueError):
discount(100, -10)
@pytest.mark.xfail(reason="Функция не валидирует процент скидки больше 100")
def test_discount_процент_больше_100_должен_быть_ошибкой():
with pytest.raises(ValueError):
discount(100, 150)
Отдельно: функция ведёт себя странно для некоторых значений, потому что вообще не валидирует входные данные.
Например:
discount(100, -10) # 110.0
discount(100, 150) # -50.0
discount(-100, 10) # -90.0
С точки зрения бизнес-логики скидки это, скорее всего, некорректно. Поэтому такие тесты помечены как xfail: они показывают ожидаемое нормальное поведение, но текущая реализация его не поддерживает.
Вот набор тестов для функции discount. Предполагаю, что функция лежит в модуле discount_module — поправьте импорт под свою структуру проекта.
import pytest
from discount_module import discount # замените на реальный путь к функции
class TestDiscountNormalCases:
"""Обычные, ожидаемые случаи применения скидки"""
def test_typical_discount_10_percent(self):
assert discount(100, 10) == 90
def test_typical_discount_25_percent(self):
assert discount(200, 25) == 150
def test_discount_with_float_price(self):
assert discount(99.99, 10) == pytest.approx(89.991)
def test_discount_with_float_percent(self):
assert discount(100, 12.5) == pytest.approx(87.5)
def test_small_percent_discount(self):
assert discount(1000, 1) == pytest.approx(990)
class TestDiscountBoundaries:
"""Граничные значения: ноль, максимум скидки, очень большие/малые числа"""
def test_zero_percent_discount_returns_same_price(self):
assert discount(100, 0) == 100
def test_zero_price_returns_zero(self):
assert discount(0, 50) == 0
def test_hundred_percent_discount_returns_zero(self):
assert discount(100, 100) == 0
def test_zero_price_and_zero_percent(self):
assert discount(0, 0) == 0
def test_very_large_price(self):
assert discount(10**9, 10) == pytest.approx(9 * 10**8)
def test_very_small_price(self):
assert discount(0.01, 10) == pytest.approx(0.009)
class TestDiscountInvalidInput:
"""
Некорректные типы входных данных.
Функция не делает явной валидации, поэтому ошибки возникают
естественным образом из-за арифметических операций над несовместимыми типами.
"""
def test_none_price_raises_type_error(self):
with pytest.raises(TypeError):
discount(None, 10)
def test_none_percent_raises_type_error(self):
with pytest.raises(TypeError):
discount(100, None)
def test_string_price_raises_type_error(self):
with pytest.raises(TypeError):
discount("100", 10)
def test_string_percent_raises_type_error(self):
with pytest.raises(TypeError):
discount(100, "10")
def test_list_as_price_raises_type_error(self):
with pytest.raises(TypeError):
discount([100], 10)
class TestDiscountStrangeBehavior:
"""
Случаи, где функция формально не падает, но ведёт себя
нелогично с точки зрения предметной области "скидка".
Тесты фиксируют ТЕКУЩЕЕ поведение, а не то, как "должно быть".
"""
def test_percent_over_100_gives_negative_price(self):
# Скидка 150% даёт отрицательную цену — в реальности это бессмысленно
assert discount(100, 150) == -50
def test_negative_percent_increases_price(self):
# Отрицательный процент скидки превращается в наценку
assert discount(100, -10) == 110
def test_negative_price_returns_negative_result(self):
# Отрицательная цена "на входе" не валидируется
assert discount(-100, 10) == -90
def test_negative_price_and_negative_percent(self):
assert discount(-100, -10) == -110
def test_bool_as_percent_is_silently_treated_as_number(self):
# bool — подтип int в Python, поэтому True/False проходят как 1/0
# без каких-либо предупреждений
assert discount(100, True) == 99
assert discount(100, False) == 100
Отдельно про странное поведение функции
Функция discount не содержит никакой валидации входных данных и предметной логики, из-за чего:
- Скидка больше 100% (
percent > 100) даёт отрицательную цену. Для реального магазина это явно ошибка, но функция её не ловит. - Отрицательный процент превращает скидку в наценку (цена увеличивается), хотя по названию функция должна только уменьшать цену.
- Отрицательная цена на входе принимается без вопросов и просто обсчитывается по формуле — в реальности цена не может быть отрицательной.
boolвместоpercent(True/False) тихо воспринимается как1/0, так как в Pythonbool— подтипint. Это может маскировать ошибки вызывающего кода.- Нет никакой валидации диапазона (
0 <= percent <= 100) и типов — любые проверки переложены на сторону вызывающего кода, что делает функцию потенциально опасной при неаккуратном использовании.
Если это предполагаемое поведение — функция в порядке. Если нет — стоит добавить проверки диапазона и типов.
Конечно, вот тесты для вашей функции discount с использованием pytest, покрывающие различные сценарии:
import pytest
# Предполагаемая функция, которую мы тестируем
def discount(price, percent):
"""
Рассчитывает цену после применения скидки.
Args:
price (float or int): Исходная цена товара.
percent (float or int): Процент скидки (от 0 до 100).
Returns:
float: Цена после применения скидки.
"""
return price - price * percent / 100
# --- Тесты для обычных случаев ---
def test_обычная_скидка_20_процентов():
"""Проверяет расчет скидки 20% на обычную цену."""
assert discount(100, 20) == 80.0
def test_обычная_скидка_50_процентов():
"""Проверяет расчет скидки 50% на обычную цену."""
assert discount(200, 50) == 100.0
def test_обычная_скидка_с_дробной_ценой():
"""Проверяет расчет скидки с дробной исходной ценой."""
assert discount(99.99, 10) == pytest.approx(89.991)
def test_обычная_скидка_с_дробным_процентом():
"""Проверяет расчет скидки с дробным процентом."""
assert discount(100, 15.5) == 84.5
def test_обычная_скидка_с_большими_числами():
"""Проверяет расчет скидки с большими значениями цены."""
assert discount(1000000, 25) == 750000.0
# --- Тесты для граничных случаев ---
def test_скидка_ноль_процентов():
"""Проверяет, что скидка 0% не изменяет цену."""
assert discount(100, 0) == 100.0
def test_скидка_сто_процентов():
"""Проверяет, что скидка 100% делает цену нулевой."""
assert discount(100, 100) == 0.0
def test_цена_ноль():
"""Проверяет, что скидка на нулевую цену всегда дает ноль."""
assert discount(0, 50) == 0.0
def test_цена_один_процент_один():
"""Проверяет скидку 1% на цену 1."""
assert discount(1, 1) == 0.99
def test_цена_очень_маленькая():
"""Проверяет скидку на очень маленькую цену."""
assert discount(0.01, 10) == pytest.approx(0.009)
# --- Тесты для неверного ввода (ожидаемое поведение функции) ---
def test_процент_скидки_отрицательный():
"""
Проверяет, что отрицательный процент скидки увеличивает цену.
Это не ошибка функции, а следствие математической формулы.
"""
assert discount(100, -10) == 110.0
def test_процент_скидки_больше_ста():
"""
Проверяет, что процент скидки больше 100% делает цену отрицательной.
Это не ошибка функции, а следствие математической формулы.
"""
assert discount(100, 120) == -20.0
def test_цена_отрицательная():
"""
Проверяет, что отрицательная цена с положительной скидкой
делает ее "менее отрицательной" (ближе к нулю).
Это не ошибка функции, а следствие математической формулы.
"""
assert discount(-100, 20) == -80.0
def test_цена_отрицательная_процент_отрицательный():
"""
Проверяет, что отрицательная цена с отрицательной скидкой
делает ее "более отрицательной" (дальше от нуля).
Это не ошибка функции, а следствие математической формулы.
"""
assert discount(-100, -20) == -120.0
# --- Тесты для ошибок (ожидаемые исключения) ---
def test_цена_не_число():
"""Проверяет, что передача нечислового значения в price вызывает TypeError."""
with pytest.raises(TypeError):
discount("abc", 10)
def test_процент_не_число():
"""Проверяет, что передача нечислового значения в percent вызывает TypeError."""
with pytest.raises(TypeError):
discount(100, "xyz")
def test_оба_аргумента_не_числа():
"""Проверяет, что передача нечисловых значений в оба аргумента вызывает TypeError."""
with pytest.raises(TypeError):
discount("abc", "xyz")
def test_цена_none():
"""Проверяет, что передача None в price вызывает TypeError."""
with pytest.raises(TypeError):
discount(None, 10)
def test_процент_none():
"""Проверяет, что передача None в percent вызывает TypeError."""
with pytest.raises(TypeError):
discount(100, None)
# --- Дополнительные тесты для точности (float comparison) ---
def test_точность_плавающей_точки():
"""
Проверяет точность вычислений с плавающей точкой, используя pytest.approx.
"""
assert discount(10, 33.33) == pytest.approx(6.667)
assert discount(100, 33.333333) == pytest.approx(66.666667)
# --- Отдельное замечание о поведении функции ---
# Замечание:
# Функция `discount` в текущей реализации не содержит внутренней логики для валидации
# входных данных (например, что процент должен быть от 0 до 100, а цена положительной).
# Она просто выполняет математическую операцию.
#
# Это приводит к следующим "странным" (но математически корректным) поведениям:
# 1. Отрицательный процент скидки увеличивает цену (работает как наценка).
# Пример: `discount(100, -10)` возвращает `110.0`
# 2. Процент скидки больше 100% делает цену отрицательной.
# Пример: `discount(100, 120)` возвращает `-20.0`
# 3. Отрицательная исходная цена обрабатывается так же, как и положительная,
# что может привести к отрицательным результатам, которые не имеют смысла
# в контексте "цены товара".
# Пример: `discount(-100, 20)` возвращает `-80.0`
#
# Если бы функция должна была строго соблюдать бизнес-логику (например, скидка от 0 до 100%,
# цена всегда положительная), то в ней следовало бы добавить проверки и, возможно,
# вызывать `ValueError` в таких случаях. Текущие тесты отражают поведение
# *данной конкретной реализации* функции.
Как запустить тесты:
- Сохраните код функции и тестов в одном файле, например,
test_discount.py. - Убедитесь, что у вас установлен
pytest:pip install pytest. - Откройте терминал в директории, где сохранен файл, и выполните команду:
pytest
Пояснения к тестам:
pytest.approx: Используется для сравнения чисел с плавающей точкой. Из-за особенностей представления чисел с плавающей точкой в компьютере, прямые сравнения (==) могут давать ложные отрицательные результаты.pytest.approxпозволяет сравнивать числа с заданной относительной или абсолютной точностью.pytest.raises(TypeError): Это контекстный менеджер, который проверяет, что код внутри него вызывает указанное исключение (TypeErrorв данном случае). Если исключение не будет вызвано, тест провалится.- Названия тестов: Старался сделать их максимально описательными на русском языке, чтобы было понятно, что именно проверяет каждый тест.
- "Неверный ввод" vs. "Ошибки":
- Неверный ввод (ожидаемое поведение): Это случаи, когда входные данные не соответствуют "здравому смыслу" (например, отрицательная скидка), но функция математически корректно обрабатывает их, не вызывая исключений. В таких случаях тесты подтверждают это "странное" поведение.
- Ошибки (ожидаемые исключения): Это случаи, когда входные данные имеют неправильный тип (например, строка вместо числа), что приводит к
TypeErrorили другим исключениям, так как функция не может выполнить арифметические операции. - Замечание о поведении: Отдельно вынесено объяснение того, как функция ведет себя при "нелогичных" входных данных, поскольку это важно для понимания ее текущей реализации. Если бы требовалось другое поведение, функцию нужно было бы доработать.
Советы
- Запустите тесты сразу: модель иногда ошибается в ожидаемых значениях.
- Скопируйте промпт кнопкой выше.
- Замените поля в фигурных скобках своими данными.
- Отправьте в нейросеть и сравните ответ с примером на этой странице.
Подробнее о структуре хорошего запроса: гид AI University.
Похожие промпты
Промпты работают лучше, когда понимаешь модель
56 официальных курсов Anthropic, OpenAI, Google и других на русском: первые уроки бесплатно, без VPN. Наборы промптов входят в полный доступ.