Воспроизведите, прежде чем исправлять — Примеры
Пример 1 — От отчёта к воспроизведению
В отчёте сказано, что сумма для участников иногда выглядит неверной, и лог ниже — единственное доказательство. Скажите, чего не хватает, затем напишите воспроизведение, которое вы построили бы до изменения любого кода.
отчёт: «сумма заказа участника была 46.20, должна была быть 42.00»
лог: INFO calculateTotal order=4471 items=3
INFO calculateTotal done total=4620 currency=GBP
Решение
спецификация: заказ участника, ожидалось 42.00, получено 46.20
пока не хватает: какой участник, цены товаров, локаль
самое маленькое воспроизведение, одна команда с фиксированным входом:
один заказ, member=true, одна позиция на 46.20, ставка участника 10%
check_total --order fixtures/member_single.json --expect 42.00
Начните с того, что действительно произошло, и выпишите ожидаемое и полученное парой: это предложение и есть спецификация, которой должно удовлетворять воспроизведение. Затем уберите всё лишнее. В отчёте упомянуты три товара, однако одного товара со скидочной ценой достаточно, чтобы доказать, что скидка не применяется. Ловушка — начать с повествования отчёта, а не с его чисел: «иногда» рассказывает о памяти рассказчика, тогда как фактами являются только значения.
Пример 2 — Сбой, случающийся один раз из пяти
Тест падает примерно в одном прогоне из пяти, а в остальных проходит; в журнале — пять прогонов на одном и том же входе. Скажите, что нужно зафиксировать, прежде чем с провалом можно будет работать, затем напишите воспроизведение и тест, который его удержит.
прогон 1: PASS
прогон 2: FAIL ожидалось 3 товара, получено 2
прогон 3: PASS
прогон 4: FAIL ожидалось 3 товара, получено 2
прогон 5: PASS
Решение
зафиксировать: зерно генератора, часы, локаль и часовой пояс, порядок сортировки
for i in 1..1000: run_case(fixed_seed = true) -> доля провалов становится 100%
test("сохраняет товар с нулевой ценой", () => {
const cart = cartWith(fixedSeed, item("free-sample", 0));
expect(cart.items()).toHaveLength(1);
});
Прогон случая тысячу раз превращает расплывчатое «иногда» в число, а фиксация зерна, часов и порядка превращает это число в определённость — в тот момент, когда становится видна разница между успешным прогоном и сбойным. Как только сбойный вход известен и устойчив, те же несколько строк становятся тестом, который следит за возвращением дефекта. Ловушка — делать это в обратном порядке: сначала менять код и несколько раз перезапускать цикл, чтобы посмотреть, не «стало ли лучше», — так нельзя отличить настоящее исправление от удачи.