Модуль 04 — Практика: TDD-цикл с агентом
Время: 210 минут · Артефакт: labs/04-oracles/
Задание 1. Одна команда проверки (30 мин)
Соберите scripts/check.sh (или make check):
#!/usr/bin/env bash
set -e
ruff check . --output-format=concise
mypy . --no-error-summary
pytest -q
Добавьте в AGENTS.md:
## Проверка
- всё: `./scripts/check.sh`
- если упало: исправляйте причину, не отключайте проверку
Приёмка: ./scripts/check.sh проходит на чистом проекте за < 60 сек.
Задание 2. Падающий тест → рабочий код (50 мин)
- Выберите функцию, которой ещё нет:
normalize_phone(s: str) -> str. - Сами напишите тесты (5 кейсов, включая граничные):
def test_normalize_phone():
assert normalize_phone("+7 (912) 345-67-89") == "+79123456789"
assert normalize_phone("89123456789") == "+79123456789"
assert normalize_phone("") == ""
assert normalize_phone("abc") == ""
assert normalize_phone("+1 222 333") == "+1222333"
- Убедитесь, что тесты падают (
ImportError— тоже падение). - Дайте агенту:
Тесты в tests/test_phone.py падают. Реализуй normalize_phone в src/utils/phone.py.
Минимальный код, проходящий все тесты. Не меняй тесты.
Приёмка: тесты зелёные, тесты не изменены (git diff tests/ пустой).
Задание 3. Агент пишет тесты по вашему списку (40 мин)
Возьмите существующую функцию без покрытия. Составьте список кейсов сами:
- вход None
- пустой список
- отрицательные числа
- дубликаты
- очень большое число
Затем:
Напиши тесты для src/x.py::func по списку кейсов ниже. Тесты должны падать,
если поведение изменится. Не используй моки без необходимости.
Приёмка: тесты действительно ловят мутацию — измените одну строку кода, убедитесь, что тест падает, верните обратно.
Задание 4. Цикл «ошибка → фикс» (40 мин)
Сломайте код намеренно (например, поменяйте условие). Запустите проверку и передайте агенту полный вывод:
./scripts/check.sh падает. Вот вывод:
<вставить целиком>
Найди причину и исправь. Объясни в двух строках, что было не так.
Повторите 2 раза с разными поломками.
Приёмка: в отчёте — вывод ошибки, дифф фикса, объяснение. Отметьте: помогал ли полный вывод по сравнению с пересказом.
Задание 5. Golden-тест (50 мин)
Для функции, генерирующей текст/JSON/отчёт:
- Создайте эталон
tests/golden/expected.json. - Тест:
def test_report_golden():
assert generate_report(SAMPLE_INPUT) == json.loads(
open("tests/golden/expected.json").read()
)
- Попросите агента изменить формат отчёта — golden упадёт — пусть обновит эталон осознанно.
Приёмка: в отчёте есть дифф эталона и объяснение, почему изменение корректно.
Критерии сдачи
check.shработает одной командой, время < 60 сек.- Тесты из задания 2 не изменены, код — минимальный.
- Есть доказательство, что тесты ловят мутацию.
- Отчёт цикла «ошибка → фикс» с полным выводом.
- Golden-тест + осознанное обновление эталона.