При каких условиях должны падать unit-тесты?

Ответ

Unit-тесты должны падать, когда они обнаруживают проблему или несоответствие ожидаемому поведению. Это их основная функция — сигнализировать о необходимости внимания к коду.

Основные условия, при которых корректно написанный unit-тест должен падать:

  1. Обнаружение бага (регрессии): Если новый код или изменения в существующем коде приводят к нарушению ранее работавшей функциональности, тесты должны это выявить. Это ключевая роль тестов в предотвращении регрессий.
  2. Изменение требований или логики: Когда функциональность, которую тестирует юнит-тест, намеренно изменяется, и тест больше не соответствует новому поведению. В этом случае тест падает, сигнализируя о необходимости его обновления в соответствии с новыми требованиями.
  3. Разработка через тестирование (TDD): При использовании TDD, тест пишется до реализации функциональности. Он должен падать, пока функциональность не будет реализована корректно.
  4. Нарушение контракта/интерфейса: Если изменяются входные параметры, возвращаемые значения или типы данных тестируемого модуля, и эти изменения несовместимы с ожиданиями теста.
  5. Устаревший или удаленный код: Если тестируемый модуль был удален или его API кардинально изменилось, тест, зависящий от него, должен падать, указывая на необходимость его удаления или переписывания.

Пример хрупкого (fragile) теста, который может падать по нерелевантным причинам:

import datetime

def get_current_hour():
    """Возвращает текущий час в формате HH."""
    return datetime.datetime.now().strftime("%H")

# Этот тест будет падать, если текущий час не 10:00
def test_get_current_hour_is_10am():
    assert get_current_hour() == "10"

Такой тест падает не из-за бага в get_current_hour, а из-за зависимости от внешнего фактора (текущего времени). Unit-тесты должны быть детерминированными — при одних и тех же входных данных они всегда должны давать один и тот же результат. Падение из-за недетерминированности указывает на проблему в самом тесте или его изоляции.

Ответ 18+ 🔞

Да ты послушай, что за дичь творится с этими юнит-тестами! Ну, в смысле, они же должны, блядь, падать, когда что-то пошло не так. Это их работа, ёпта! Сигнализировать, что пора, сука, мозги включить и в код заглянуть.

Вот основные случаи, когда нормальный, не ебанутый тест обязан грохнуться с треском:

  1. Баг вылез, регрессия: Ты там что-то подкрутил, добавил новую фичу, а старая, сука, сломалась. Тест должен орать как резаный: «Мужик, тут пиздец, нахуй! Проверь, что ты натворил!» Это его святая обязанность — регрессии ловить.
  2. Логику поменяли: Продукт-менеджер пришёл и сказал: «А давайте теперь не так, а эдак». Ты логику переписал, а тест-то про старую. Он, естественно, падает. Это сигнал: «Э, дружок-пирожок, а меня кто обновлять будет? Подгони под новые правила!»
  3. TDD (Разработка через тестирование): Тут вообще цирк. Сначала пишешь тест на то, чего ещё нет. Он, ясное дело, падает, потому что функциональности-то ноль. Потом пишешь код, пока тест не зазеленеет. Падение на старте — это норма, ожидаемо и правильно.
  4. Контракт порвали: Твой модуль раньше возвращал число, а теперь, блядь, строку. Или аргументы другие требует. Тест, который на старый контракт заточен, сдохнет моментально. И правильно сделает: «Ты чего мне подсовываешь, урод? Я не это ждал!»
  5. Код выкинули на свалку: Удалили целый модуль, а тест на него остался. Ну он и падает, как дурак. Это намёк: «Либо меня удали, либо перепиши с нуля, если что-то новое появилось».

А вот пример теста-идиота, который падает просто потому, что он долбоёб:

import datetime

def get_current_hour():
    """Возвращает текущий час в формате HH."""
    return datetime.datetime.now().strftime("%H")

# Этот тест будет падать, если текущий час не 10:00
def test_get_current_hour_is_10am():
    assert get_current_hour() == "10"

Ну что это за пиздопроёбина? Этот тест сдохнет в 11 утра, в 3 ночи, да в любое другое время, кроме 10:00! Он падает не потому, что в get_current_hour баг, а потому что он сам, сука, привязан к реальному времени. Юнит-тесты должны быть стабильными, как швейцарские часы! Один и тот же вход — один и тот же результат. А если он падает из-за какой-то внешней хуйни вроде времени, сети или погоды на Марсе — это проблема в самом тесте, его надо переделывать.