Перейти к основному содержимому

Extreme Programming, TDD и BDD

Разработчику
Связь с другими статьями

Обзор Agile — глава 3. Выбор процесса — глава 4. Тестирование — раздел 7-05. Рефакторинг — Фаулер.


Extreme Programming (XP)

XP (Extreme Programming) — набор инженерных практик Agile, описанных Kent Beck. Идея: довести полезные приёмы (тесты, ревью, частые релизы) до системной дисциплины команды, а не оставлять их на усмотрение отдельных разработчиков.

XP появился в конце 1990-х на проектах с высокой неопределённостью требований. Сегодня отдельные практики XP (TDD, CI, pairing) используют и в Scrum-, и в Kanban-командах без формального "мы делаем XP".

Практики XP

ПрактикаСмыслСвязь с энциклопедией
TDDСначала тест, потом кодЭта статья, уровни тестов
Pair programmingДва разработчика на одной задачеОнбординг
Continuous integrationЧастая сборка и интеграция в общую веткуDevOps CI/CD
RefactoringУлучшение структуры без смены поведенияФаулер
Small releasesМаленькие поставки в productionDoD
Coding standardsЕдиный стиль кода7.10
Collective ownershipЛюбой может править любой модуль (с review)Code review, bus factor
Sustainable paceРабота без хронического переработаКультура команды
On-site customerЗаказчик доступен для вопросовPO
MetaphorОбщий язык архитектуры для командыADR

XP не требует ролей Scrum (Scrum Master, Product Owner в каноническом виде). Сочетается со Scrum или Kanban: Scrum задаёт ритм, XP — инженерное качество.

Ценности XP

ЦенностьНа практике
CommunicationPairing, standup, общие стандарты
SimplicityYAGNI — не пишем лишнего
FeedbackTDD, CI, частые релизы
CourageРефакторинг, честная оценка
RespectReview без токсичности
С чего начать XP в команде

Не внедряйте все практики сразу. Типичная последовательность: CI → coding standards → TDD на критичном модуле → pairing на сложных задачах → small releases.


TDD — Test-Driven Development

TDD — разработка через тесты. Вы сначала описываете желаемое поведение в тесте, потом пишете минимальный код, затем улучшаете дизайн.

Цикл Red → Green → Refactor

1. Red — написать падающий тест на желаемое поведение.

Тест должен падать по правильной причине (нет реализации), а не из-за синтаксической ошибки.

2. Green — написать минимальный код, чтобы тест прошёл.

Не добавляйте функциональность "на будущее". Цель — зелёные тесты, не красота.

3. Refactor — улучшить структуру кода; тесты остаются зелёными.

Удалить дублирование, переименовать, вынести методы. Рефакторинг безопасен, потому что тесты страхуют.

Пример на псевдокоде: калькулятор скидки

Red — тест:

test('скидка 10% для суммы от 1000', () => {
expect(calculateDiscount(1000)).toBe(100);
});

Запуск → FAIL (функции нет).

Green — минимум:

function calculateDiscount(amount) {
if (amount >= 1000) return amount * 0.1;
return 0;
}

Запуск → PASS.

Refactor — константа, граничные случаи:

const DISCOUNT_THRESHOLD = 1000;
const DISCOUNT_RATE = 0.1;

function calculateDiscount(amount) {
if (amount >= DISCOUNT_THRESHOLD) {
return amount * DISCOUNT_RATE;
}
return 0;
}

Добавить тесты на 999, 0, отрицательные значения — снова цикл Red-Green-Refactor.

Результаты TDD

  • Спецификация поведения в коде тестов — живой документ.
  • Меньше лишней реализации — пишете только то, что требует тест.
  • Безопасный рефакторинг — регрессия ловится за секунды в CI.
  • Лучший дизайн — тестируемый код обычно с меньшей связностью.

Где TDD особенно полезен

ОбластьПочему
Деньги, налоги, комиссииОшибка дорого стоит
Права доступа, RBACМного граничных случаев
Парсинг, валидацияТабличные тесты
Доменная логика без UIБыстрый feedback loop
Баг-фиксRegression test сначала

Где TDD применять осторожно

ОбластьАльтернатива
Прототип UI "посмотреть как выглядит"Ручная проверка, потом тесты
Исследование API без документацииSpike, потом TDD на стабильном API
Одноразовый скрипт миграцииSmoke-тест на копии данных
Legacy без тестовCharacterization tests, потом TDD на новом коде

Уровни тестов — unit, integration, E2E. Практика на учебной задаче — лабораторный кейс TDD.

TDD и coverage

Coverage (покрытие строк/веток) — метрика, а не цель. TDD часто даёт высокое покрытие доменной логики, но:

  • 100% coverage не гарантирует отсутствие багов;
  • тесты "ради процента" после кода — не TDD;
  • в DoD разумно указать порог для критичных модулей, а не для всего репозитория.

BDD — Behavior-Driven Development

BDD — описание поведения системы на языке, понятном бизнесу, аналитику и QA. Часто используют формат Gherkin (Given-When-Then).

BDD не заменяет TDD: TDD — на уровне unit-тестов разработчика; BDD — на уровне сценариев приёмки, которые могут автоматизироваться и читаться на ревью.

Структура сценария Gherkin

Feature: Создание заявки
Как авторизованный пользователь
Я хочу создать заявку
Чтобы отправить её на согласование

Scenario: Успешное создание черновика
Given пользователь авторизован
And баланс счёта не менее 1000
When он создаёт заявку на сумму 1000
Then заявка в статусе "Черновик"
And сумма заявки равна 1000

Scenario: Отказ при недостаточном балансе
Given пользователь авторизован
And баланс счёта 500
When он создаёт заявку на сумму 1000
Then отображается ошибка "Недостаточно средств"
And заявка не создана

Ключевые слова Gherkin

Ключевое словоНазначение
FeatureГруппа связанных сценариев
ScenarioОдин конкретный случай
GivenПредусловия (контекст)
WhenДействие пользователя или системы
ThenОжидаемый результат
And / ButПродолжение Given/When/Then
BackgroundОбщие Given для всех сценариев
Scenario OutlineПараметризованные сценарии с Examples

Scenario Outline — табличные примеры

Scenario Outline: Валидация email
When пользователь вводит email "<email>"
Then результат валидации "<result>"

Examples:
| email | result |
| user@example.com | valid |
| invalid | invalid |
| user@ | invalid |

Инструменты BDD

ИнструментСтек
CucumberJava, JS, Ruby и др.
SpecFlow.NET
pytest-bddPython
BehavePython
Cypress + cucumberE2E веб

Связь с acceptance criteria и техниками тест-дизайна.

Кто пишет сценарии

РольУчастие
Аналитик / POФормулировка поведения, приоритеты
QAГраничные случаи, негативные сценарии
РазработчикСвязь с step definitions, автоматизация
БизнесРевью на plain language (three amigos)

Three amigos — короткая встреча PO + dev + QA перед разработкой фичи: согласовать сценарии до кода.

Антипаттерн BDD

Gherkin-файлы, которые никто не читает на планировании и которые дублируют технические детали UI — дорогая декорация. Сценарий должен описывать поведение, а не клики по xpath.

Хороший и плохой сценарий

Плохо (слишком технически):

When пользователь кликает #submit-btn
Then div.error.visible == true

Хорошо (поведение):

When пользователь отправляет форму без обязательного поля "Email"
Then отображается сообщение "Укажите email"
And форма не отправлена

Pair programming

Pair programming — два разработчика работают над одной задачей за одним рабочим местом (или в shared IDE / screen share).

Роли

РольДелает
DriverПишет код, управляет клавиатурой
NavigatorДумает о дизайне, замечает ошибки, ищет edge cases

Роли меняют каждые 20–40 минут.

Форматы

ФорматКогда
Classic pairingСложная логика, онбординг
Strong-styleNavigator говорит что делать, driver только печатает — для обучения
Mob programmingВся команда на одной задаче — редкие архитектурные решения
Async pairingPR + быстрые созвоны — для удалённых команд

Польза

  • меньше дефектов и bus factor;
  • быстрый онбординг junior (7.17/7);
  • общее владение кодовой базой;
  • живое code review.

Когда pairing уместен

  • новый модуль или незнакомый стек;
  • критичная бизнес-логика (деньги, безопасность);
  • первые недели нового сотрудника;
  • застряли на баге больше 2 часов — второй взгляд.

Когда pairing не обязателен

  • мелкие правки по одному файлу;
  • рутинные задачи с готовым шаблоном;
  • исследование, где нужна тишина (потом — короткий sync).
Pairing как слежка

Если senior сидит с junior только чтобы "контролировать" без объяснений — ломается психологическая безопасность. Pairing — совместное решение задачи, а не надзор.


Когда внедрять практики

ПрактикаРекомендуемый моментМинимум для старта
CIС первого дня проектаСборка + unit-тесты на push
TDDС критичной доменной логикиОдин модуль как pilot
Pair programmingСложные модули, онбординг junior2–4 часа в неделю на пару
BDDКогда PO и QA читают сценарии на ревью1 feature end-to-end
Small releasesПосле базового CI и stageРелиз раз в 2 недели
RefactoringПостоянно, в рамках задачиПравило boy scout
Coding standardsДо второго PR в репоLinter в CI

Цель — не "100% TDD на всё", а осознанное покрытие рискованных зон.

Дорожная карта внедрения (пример для команды из 5 dev)

Неделя 1–2

Неделя 3–4

  • TDD pilot на модуле billing или auth.
  • DoD: новая доменная логика — unit-тесты.

Месяц 2

  • BDD: один user story с Gherkin в репо, автотест в CI.
  • Pairing: ротация на сложных тикетах.

Месяц 3+

  • Small releases по расписанию.
  • Retrospective: что из XP оставить, что упростить.

Антипаттерны

АнтипаттернПочему плохоЧто делать
Тесты после кода ради coverageНе ловит design flawsTDD на новом коде
BDD-декорацияЗатраты без согласованияThree amigos, читаемые сценарии
Pairing как слежкаВыгорание juniorРотация, обучающий тон
TDD на всё включая UI layoutМедленно, хрупкоE2E выборочно, unit на логику
Зелёные тесты без assertЛожное спокойствиеReview тестов как кода
Refactor без тестовНовые багиСначала characterization test
CI красный "потом починим"Ломает довериеFix or revert в тот же день

Связь с Definition of Done

DoD команды может включать:

  • доменная логика покрыта unit-тестами;
  • критичные сценарии описаны в BDD и проходят в CI;
  • нет merge без зелёного pipeline;
  • pairing или review для критичных модулей;
  • нет нового кода без обновления документации API (OpenAPI).

Пример фрагмента DoD:

- [ ] Unit-тесты для новой доменной логики
- [ ] Gherkin-сценарии для AC из тикета (если есть)
- [ ] CI green
- [ ] Code review от 1+ разработчика

Примеры из практики

Пример 1. Модуль расчёта НДС

  • TDD: таблица ставок, округление, граничные суммы.
  • BDD: сценарий "счёт-фактура для юрлица" для QA и бухгалтерии.
  • Pairing: junior + senior на первом релизе модуля.

Пример 2. REST API заказов

  • TDD: сервисный слой, моки репозитория.
  • BDD: Feature: Оформление заказа — автотест через HTTP.
  • CI: unit + integration + smoke BDD на stage.

Пример 3. Legacy без тестов

  • Не TDD на старый код сразу.
  • Characterization test на текущее поведение.
  • Новые фичи — только через TDD в новых классах.

FAQ

TDD замедляет разработку?

На первых неделях — да. На горизонте месяцев экономит время на отладку и регрессии. На критичной логике окупается быстрее.

Нужен ли TDD, если есть QA?

Да, роли разные. Unit-тесты от dev — быстрый feedback; QA — integration, E2E, exploratory (100).

BDD без автоматизации имеет смысл?

Да, как согласованные AC в Gherkin, даже если step definitions появятся позже.

Pair programming для удалённых команд?

Да: VS Code Live Share, JetBrains Code With Me, Zoom + shared control. Важны таймбоксы и смена ролей.

XP без Scrum возможен?

Да. Kanban + XP-практики — распространённая связка.

Как убедить менеджера в pairing?

Метрики: меньше багов на review, быстрее онбординг, меньше блокеров "единственный кто знает модуль".


См. также