{/ Эта страница автоматически создается на основе файла SKILL.md навыка с помощью сайта site/scripts/generate-skill-docs.py. Редактируйте исходный код SKILL.md, а не эту страницу. /}

Разработка через тестирование

TDD: применять RED-GREEN-REFACTOR, тесты перед кодом.

Метаданные навыков

Источник В комплекте (устанавливается по умолчанию)
Путь навыки/разработка программного обеспечения/разработка через тестирование
Версия 1.1.0
Автор Агент Гермеса (адаптировано из обры/сверхспособностей)
Лицензия Массачусетский технологический институт
Платформы Linux, MacOS, Windows
Теги тестирование, tdd, разработка, качество, красно-зелёный-рефактор
Сопутствующие навыки систематическая-отладка, writing-plans, разработка-под агентом

Ссылка: полная версия SKILL.md:::информация

Ниже приведено полное определение навыка, которое Гермес загружает при активации этого навыка. Это то, что агент видит в качестве инструкций, когда навык активен.

Разработка через тестирование (TDD)

Обзор

Сначала напишите тест. Смотри, как это терпит неудачу. Напишите минимальный код для передачи.

Основной принцип: Если вы не видели, как тест провалился, вы не знаете, верен ли он.

Нарушение буквы правил — нарушение духа правил.

Когда использовать

Всегда: - Новые возможности - Исправлены ошибки - Рефакторинг - Изменения в поведении

Исключения (сначала спросите у пользователя): - Одноразовые прототипы - Сгенерированный код - Файлы конфигурации

Думаете «пропустить TDD хотя бы один раз»? Останавливаться. Это рационализация.

Железный закон

NO PRODUCTION CODE WITHOUT A FAILING TEST FIRST

Писать код перед тестом? Удалите его. Начни сначала.

Без исключений: - Не храните это как «справку». - Не «адаптируйте» его при написании тестов. - Не смотри на это - Удалить значит удалить

Реализуйте только что из тестов. Период.

Цикл «красный-зеленый-рефакторинг»

RED — запись неудачного теста

Напишите один минимальный тест, показывающий, что должно произойти.

Хороший тест:

def test_retries_failed_operations_3_times():
    attempts = 0
    def operation():
        nonlocal attempts
        attempts += 1
        if attempts < 3:
            raise Exception('fail')
        return 'success'

    result = retry_operation(operation)

    assert result == 'success'
    assert attempts == 3

Ясное имя, тесты реального поведения, одно.

Плохой тест:

def test_retry_works():
    mock = MagicMock()
    mock.side_effect = [Exception(), Exception(), 'success']
    result = retry_operation(mock)
    assert result == 'success'  # What about retry count? Timing?

Расплывчатое название, тесты имитируют не настоящий код.

Требования: - Одно поведение на тест - Четкое описательное имя («и» в имени? Разделите его) - Настоящий код, а не имитация (если это действительно неизбежно). - Имя описывает поведение, а не реализацию.

Проверьте КРАСНЫЙ — посмотрите, не получится

ОБЯЗАТЕЛЬНО. Никогда не пропускайте.

# Use terminal tool to run the specific test
pytest tests/test_feature.py::test_specific_behavior -v

Подтвердите: - Тест не пройден (не ошибки из-за опечаток) - Ожидается сообщение об ошибке - Не удалось, поскольку функция отсутствует.

Тест пройден немедленно? Вы тестируете существующее поведение. Исправьте тест.

Ошибки теста? Исправьте ошибку и повторяйте тест, пока он не завершится правильно.

ЗЕЛЕНЫЙ — минимальный код

Напишите простейший код для прохождения теста. Ничего больше.

Хороший:

def add(a, b):
    return a + b  # Nothing extra

Плохой:

def add(a, b):
    result = a + b
    logging.info(f"Adding {a} + {b} = {result}")  # Extra!
    return result

Не добавляйте функции, не рефакторизируйте другой код и не «улучшайте» его за пределами теста.

Жульничество допустимо в ЗЕЛЕНОМ цвете: - Возвращаемые значения жесткого кода - Копипаст - Дублирующийся код - Пропустить крайние случаи

Исправим это в REFACTOR.

Подтвердите ЗЕЛЕНЫЙ — смотрите, как проходит

ОБЯЗАТЕЛЬНО.

# Run the specific test
pytest tests/test_feature.py::test_specific_behavior -v

# Then run ALL tests to check for regressions
pytest tests/ -q

Подтвердите: - Тест проходит - Остальные тесты все еще проходят - Вывод нетронутый (без ошибок и предупреждений)

Тест не пройден? Исправьте код, а не тест.

Другие тесты не прошли? Исправьте регрессии прямо сейчас.

РЕФАКТОР — Очистка

Только после зеленого: - Удалить дублирование - Улучшить имена - Извлечь помощников - Упрощать выражения

Всегда держите тесты зелеными. Не добавляйте поведение.

Если тесты не пройдены во время рефакторинга: Отмените немедленно. Делайте меньшие шаги.

Повторить

Следующий неудачный тест на следующее поведение. Один цикл за раз.

Почему порядок имеет значение

"После этого я напишу тесты, чтобы убедиться, что это работает"

Тесты, написанные после кода, проходят немедленно. Прохождение сразу ничего не доказывает: - Может протестировать не ту вещь - Может проверять реализацию, а не поведение - Могут быть пропущены крайние случаи, о которых вы забыли. - Вы никогда не видели, чтобы он поймал ошибку

Принцип «сначала тест» заставляет вас видеть, что тест не пройден, доказывая, что он действительно что-то проверяет.

"Я уже вручную протестировал все крайние случаи"

Ручное тестирование носит разовый характер. Вы думаете, что проверили все, но: - Нет записей о том, что вы тестировали - Невозможно выполнить повторный запуск при изменении кода. - Легко забыть дела под давлением - «Когда я попробовал, это сработало» ≠ всеобъемлющее

Автоматизированные тесты носят систематический характер. Они каждый раз бегут одинаково.

"Удаление X часов работы — расточительство"

Заблуждение о невозвратных издержках. Время уже ушло. Ваш выбор сейчас: - Удаление и перезапись с помощью TDD (высокая достоверность) - Сохраните его и добавьте тесты после (низкая достоверность, вероятны ошибки).

«Отходы» — это хранение кода, которому нельзя доверять.

"TDD догматичен, быть прагматичным означает адаптироваться"

TDD прагматичен: - Находит ошибки перед фиксацией (быстрее, чем отладка после) - Предотвращает регрессии (тесты немедленно ловят сбои) - Поведение документов (тесты показывают, как использовать код) - Включает рефакторинг (свободное изменение, тесты ловят сбои)

«Прагматичные» ярлыки = отладка в производстве = медленнее.

"Испытания после достижения одних и тех же целей — это дух, а не ритуал"

Нет. Тесты - после ответа "Что это делает?" Тесты-первый ответ «Что это должно делать?»

Тесты после зависят от вашей реализации. Вы тестируете то, что создали, а не то, что требуется. Тесты — сначала принудительно выявляют крайние случаи перед реализацией.

Распространенные рационализации

Извините Реальность
«Слишком просто для тестирования» Простые взломы кода. Тест занимает 30 секунд.
«Я проверю после» Прохождение тестов сразу ничего не доказывает.
«Испытания после достижения тех же целей» Tests-after = «что это делает?» Сначала тесты = «что это должно делать?»
«Уже проверено вручную» Специальное ≠ систематическое. Нет записи, невозможно перезапустить.
«Удалять X часов — расточительство» Заблуждение о невозвратных издержках. Хранение непроверенного кода — это технический долг.
«Сохраняйте как справку, сначала напишите тесты» Вы адаптируете его. Это тестирование после. Удалить значит удалить.
«Сначала нужно изучить» Отлично. Отбросьте исследование, начните с TDD.
«Тестирование сложно = конструкция неясна» Прослушайте тест. Трудно протестировать = сложно использовать.
«TDD меня замедлит» TDD быстрее, чем отладка. Прагматичный = сначала тест.
«Ручной тест быстрее» Руководство не доказывает крайние случаи. Вы будете повторно тестировать каждое изменение.
«Существующий код не имеет тестов» Вы улучшаете его. Добавьте тесты для кода, к которому вы прикасаетесь.

Красные флажки — ОСТАНОВИТЕСЬ и начните сначала

Если вы поймаете себя на том, что делаете что-либо из этого, удалите код и перезапустите с помощью TDD:

Все это означает: Удалить код. Начните заново с TDD.

Контрольный список проверки

Прежде чем отмечать работу как завершенную:

Не можете отметить все флажки? Вы пропустили TDD. Начни сначала.

Когда застрял

Проблема Решение
Не знаю, как проверить Напишите желаемый API. Сначала напишите утверждение. Спросите пользователя.
Тест слишком сложен Дизайн слишком сложный. Упростите интерфейс.
Должен издеваться над всем Код слишком связан. Используйте внедрение зависимостей.
Огромная тестовая установка Извлеките помощников. Все еще сложный? Упростите дизайн.

Интеграция агента Гермеса

Запуск тестов

Используйте инструмент «терминал» для запуска тестов на каждом этапе:

# RED — verify failure
terminal("pytest tests/test_feature.py::test_name -v")

# GREEN — verify pass
terminal("pytest tests/test_feature.py::test_name -v")

# Full suite — verify no regressions
terminal("pytest tests/ -q")

С делегатом_задачи

При отправке субагентов для реализации включите TDD в цель:

delegate_task(
    goal="Implement [feature] using strict TDD",
    context="""
    Follow test-driven-development skill:
    1. Write failing test FIRST
    2. Run test to verify it fails
    3. Write minimal code to pass
    4. Run test to verify it passes
    5. Refactor if needed
    6. Commit

    Project test command: pytest tests/ -q
    Project structure: [describe relevant files]
    """,
    toolsets=['terminal', 'file']
)

С систематической отладкой

Ошибка найдена? Напишите неудачный тест, воспроизводящий его. Следуйте циклу TDD. Тест доказывает исправление и предотвращает регрессию.

Никогда не исправляйте ошибки без тестирования.

Тестирование антипаттернов

Последнее правило

Production code → test exists and failed first
Otherwise → not TDD

Никаких исключений без явного разрешения пользователя.