Как система должна вести себя при сумме, выходящей за допустимые диапазоны значений
Что проверяют
Умеете ли вы превратить «сумма не должна выходить за пределы» в набор решений: где проверять, что отвечать клиенту и как это тестировать. Следом почти всегда спрашивают, почему для денег нельзя брать float и какие граничные значения вы бы проверили.
Как отвечать
Начните с того, что проверка живёт в нескольких слоях, и у каждого своя задача:
- граница API: схема на Pydantic, например
Annotated[Decimal, Field(gt=0, le=Decimal("100000"), decimal_places=2)]. FastAPI на невалидное тело сам отдаёт 422 с перечнем полей; - доменный слой: правила, зависящие от контекста (лимит по тарифу, остаток на счёте), проверяет сервис и бросает своё исключение вроде
AmountOutOfRange, а обработчик переводит его в понятный ответ; - база:
NUMERIC(12, 2)иCHECK (amount > 0)как последний рубеж, если данные придут в обход API.
Сумму вне диапазона отклоняют целиком, а не обрезают до максимума. Ответ содержит код ошибки и допустимые границы, чтобы клиент мог исправить ввод. Для крупных, но формально допустимых сумм уместна отдельная ветка: не отказ, а ручная проверка или дополнительное подтверждение.
Тесты: pytest.mark.parametrize по классам эквивалентности и границам. Минимум, минимум минус копейка, максимум, максимум плюс копейка, ноль, отрицательное число, лишний знак после запятой, строка вместо числа. Для инвариантов хорошо подходит Hypothesis.
Где спотыкаются
Берут float. 0.1 + 0.2 не равно 0.3, и сумма на самой границе начинает то проходить, то нет. Деньги хранят в Decimal или в целых копейках.
Пишут проверку вида if amount < 0 or amount > limit. Значение float("nan") ложно в любом сравнении и спокойно её проходит.
Проверяют только на фронтенде. Запрос из curl или из старой версии клиента обходит такую валидацию, поэтому серверная проверка обязательна.