Введение
Little Pine Goods готовит расчёты стоимости небольших подарков с самовывозом. Покупатель сообщает, что предложение FRIEND10 больше не даёт обещанной скидки. Недавняя история также содержит полезные обновления товаров, формулировок и самовывоза, поэтому возврат всего магазина к старой версии потерял бы корректную работу.
Выполните обычный заказ и ошибочный подарочный заказ, затем используйте подготовленный детерминированный тест бизнес-результата для классификации старых версий. Немного потренируйтесь в ручном двоичном поиске Git, прежде чем поручить автоматизацию тому же тесту. Сравните первый неисправный снимок с его непосредственным родителем, выйдите из поиска и исправьте текущий магазин, сохранив более поздние обновления. Доставьте полный файл расчёта для покупателя вместе с исправляющим коммитом.
Необходимые предварительные навыки — базовая навигация в терминале, коммиты, ветки и чтение простых log/diff. Git bisect, временные переключения с отсоединённым HEAD, коды выхода теста и небольшое изменение файла предложений объясняются здесь. Python и программа расчёта подготовлены; вы запускаете их, не пишете Python. Это настоящая локальная история Git и файловый инструмент расчёта на одной учебной машине, с вымышленными заказами и ценами в EUR. Сайт, учётная запись на хостинге или сетевое развёртывание не нужны. Используйте стандартный Terminal. Продолжительность 50 минут — авторская оценка.
Найдите первый неправильный расчёт
На этом шаге вы установите правильный бизнес-результат, проверите настоящие исторические снимки и найдёте границу, на которой скидка стала неправильной.
Начните в Terminal и войдите в репозиторий магазина:
cd /home/labex/project/quote-desk/shop
Команда cd меняет каталог этого терминала. Если вы ошиблись в пути, используйте pwd, чтобы вывести своё положение, и ls, чтобы показать содержимое каталога, затем повторите полную cd выше. Обычные ошибки навигации не требуют сброса VM.
Прочитайте запрос покупателя. Команда cat показывает текстовый файл; .. означает родительский каталог:
cat ../request.txt
FRIEND10 обещает скидку 10% от суммы товаров. Доставки и налога нет. Подарочный заказ — три походные кружки по EUR 16.00: сумма товаров EUR 48.00, скидка EUR 4.80, итог EUR 43.20. Существующие каталог, заказ и правила предложения — исходные факты задачи; не меняйте их под ошибочный результат.
Сначала выполните обычный заказ. Команда python3 запускает предоставленную программу quote.py; её следующий аргумент — подготовленный файл заказа. Редактировать или понимать исходный код Python не требуется:
python3 quote.py ../orders/plain.order
Заказ одной кружки использует купон NONE. Ожидаются сумма товаров и итог EUR 16.00, скидка EUR 0.00, текущее приветствие и самовывоз в субботу до 16:00. Это показывает полезный нормальный расчёт.
Выполните заказ из сообщения покупателя:
python3 quote.py ../orders/gift.order
Чтобы прочитать собственный код выхода последней команды, используйте значение оболочки $?. Команда echo выводит это значение. Выполните её сразу после команды расчёта:
echo $?
Ожидается 0: программа выполнилась успешно, хотя денежный результат неправильный.
Программа работает, но расчёт неверен: скидка EUR 0.48 и итог EUR 47.52. Успешное завершение программы отличается от правильного бизнес-ответа.
Подготовленный тест находится вне репозитория, поэтому переключение на старые версии не может его заменить. Он запускает настоящую программу расчёта для нескольких количеств и контрольного случая без купона, сравнивая полные результаты с неизменными правилами предложения. Запустите его:
python3 /opt/labex/quote-desk/check.py
Сразу прочитайте код выхода этого теста с помощью того же значения оболочки:
echo $?
Ожидается 1: этот тест обнаруживает несоответствие бизнес-результата.
Ожидаются строки FAIL для FRIEND10 и собственный код выхода 1. Контрольные случаи NONE проходят. Тест возвращает 0 для правильных расчётов, 1 для этой бизнес-ошибки и 128, если не может проверить версию; невозможность проверки должна остановить поиск, а не считаться наугад регрессией скидки. В этой подготовленной истории нет ошибок сборки или пропускаемых версий.
Изучите текущую ветку и чистое состояние. branch --show-current выводит ветку; --short даёт компактный список файлов:
git branch --show-current
git status --short
Ожидаются main и отсутствие вывода изменённых файлов. Сохраняйте магазин чистым во время поиска. Прочитайте историю: --no-pager выводит напрямую, не открывая просмотрщик с прокруткой, --oneline сокращает записи, а --decorate подписывает ветки и теги:
git --no-pager log --oneline --decorate
Неподвижный тег incident-tip отмечает полученную текущую вершину, а known-good — более раннюю работающую версию. Темы коммитов описывают работу, но их формулировки не доказывают, когда расчёт сломался. Сохраните оба тега и все полученные коммиты.
Параметр теста --revision запускает выбранный снимок коммита во временном изолированном каталоге, не меняя и не исправляя ваше рабочее состояние. Установите обе границы по настоящему поведению:
python3 /opt/labex/quote-desk/check.py --revision known-good
python3 /opt/labex/quote-desk/check.py --revision incident-tip
Первая команда должна пройти с кодом 0. Вторая должна завершиться неудачей с кодом 1. Хорошая версия и более поздняя плохая ограничивают поиск. В этом упражнении ошибка появляется один раз, и более позднего исправления в этом интервале нет.
Классифицируйте две версии вручную
Git bisect сужает этот интервал, проверяя версии между границами. Начните с известной плохой ревизии первым аргументом и известной хорошей вторым:
git bisect start incident-tip known-good
Git переключается на средний снимок и выводит оставшийся интервал. Во время поиска отсоединённый HEAD (detached HEAD) означает, что вы просматриваете коммит напрямую, а не перемещаете main. Не редактируйте и не создавайте коммиты в этих временных версиях.
Запустите тот же тест на выбранном снимке:
python3 /opt/labex/quote-desk/check.py
В этом подготовленном сценарии первый выбор завершается неудачей с кодом 1. Классифицируйте наблюдаемую версию как плохую; bad описывает результат бизнес-теста, а не сообщение коммита:
git bisect bad
Git выбирает другой снимок. Проверьте его вместо угадывания:
python3 /opt/labex/quote-desk/check.py
Этот выбор проходит с кодом 0. Запишите наблюдение:
git bisect good
Git снова сужает интервал. Вы увидели, как каждый результат исключает часть пространства поиска. Чтобы потренироваться в автоматическом пути с теми же исходными границами, сначала выйдите из незавершённого поиска. Команда bisect reset очищает состояние поиска и возвращает к ветке и ревизии, на которых он начался; она не отменяет коммиты:
git bisect reset
git branch --show-current
Ожидается main. Если во время тренировки вы неверно классифицировали версию, тот же reset и новый запуск позволяют повторить поиск по настоящим результатам теста, не отбрасывая файлы.
Поручите поиск тесту
Начните снова, затем передайте bisect run ту же полную команду теста. Git использует собственный код выхода каждого запуска, чтобы автоматически выбирать good или bad:
git bisect start incident-tip known-good
git bisect run python3 /opt/labex/quote-desk/check.py
Ожидаются несколько запусков теста и строка, заканчивающаяся is the first bad commit. Сама команда поиска завершается с кодом 0, если успешно находит границу, хотя некоторые отдельные тесты расчёта завершились неудачей. Идентификаторы коммитов могут отличаться.
Ссылка Git bisect/bad указывает на найденный первый плохой коммит. Текущий HEAD всё ещё может быть последней проверенной хорошей версией; не считайте его автоматически найденным результатом. Прочитайте настоящий патч кандидата. Команда show выбирает этот коммит и его патч; -- отделяет путь файла:
git --no-pager show bisect/bad -- discounts.txt
Процент FRIEND10 изменился с 10 на 1. Проверьте обе стороны внешним тестом. Завершающий ^ выбирает одного непосредственного первого родителя коммита, поэтому bisect/bad^ — версия непосредственно перед кандидатом, а не целый диапазон:
python3 /opt/labex/quote-desk/check.py --revision bisect/bad
python3 /opt/labex/quote-desk/check.py --revision bisect/bad^
Ожидается, что кандидат завершится неудачей с кодом 1, а его родитель пройдёт с кодом 0. Значения и настоящее поведение согласуются. Оставьте завершённый поиск открытым для этой проверки; затем вы вернётесь к текущему магазину перед редактированием.
Исправьте текущий магазин и доставьте расчёт
На этом шаге вы выйдете из исторического поиска, сохраните целевое исправление в текущей ветке и доставите полный расчёт, не потеряв более поздние товары и сведения о самовывозе.
Оставайтесь в Terminal, в /home/labex/project/quote-desk/shop. Вернитесь в исходную ветку изученной командой завершения поиска:
git bisect reset
git branch --show-current
git --no-pager log -1 --oneline --decorate
git status --short
Ожидаются main, полученная вершина с меткой incident-tip и отсутствие вывода изменённых файлов. Параметр журнала -1 ограничивает вывод новейшим коммитом. Не исправляйте отсоединённую историческую версию и не заменяйте весь магазин версией known-good: более поздняя полезная работа должна войти в результат.
Прочитайте небольшой файл предложений и текущие сведения, которые нужно сохранить:
cat discounts.txt
cat welcome.txt pickup.txt care.txt
cat catalog.json
Текущее дерево включает Trail pin, новое приветствие и самовывоз в субботу до 16:00. Неправилен только процент FRIEND10. Файл предложений содержит по одной настройке CODE=integer-percent на строку; TRAIL15 остаётся 15, а STUDENT5 — 5.
Замените только этот небольшой файл. Команда printf выводит значения по формату: %s означает текст, а \n добавляет перевод строки после каждого переданного значения. Одинарные кавычки сохраняют буквальный текст. > записывает вывод в указанный файл, заменяя только этот файл:
printf '%s\n' 'FRIEND10=10' 'TRAIL15=15' 'STUDENT5=5' > discounts.txt
Изучите настоящее исправление. Обычный diff сравнивает рабочие файлы с индексом — областью подготовки Git:
git --no-pager diff -- discounts.txt
Ожидается только возврат FRIEND10 с 1 на 10. Задайте локальные данные автора коммита перед записью исправления. Параметр --local позволяет избежать глобальной конфигурации; кавычки объединяют имя с пробелами в одно значение. Эти вымышленные примеры можно заменить:
git config --local user.name "Little Pine Maintainer"
git config --local user.email "maintainer@little-pine.example"
Подготовьте этот файл с помощью add. Изучите подготовленный патч с --cached, который сравнивает индекс с текущим коммитом:
git add discounts.txt
git --no-pager diff --cached -- discounts.txt
Создайте коммит целевого исправления. Параметр -m задаёт осмысленное сообщение напрямую:
git commit -m "Restore the promised FRIEND10 discount"
Сравните с неподвижной полученной вершиной. Это один новый исправляющий коммит, сохраняющий все исходные коммиты вместо переписывания истории:
git --no-pager diff incident-tip HEAD
git --no-pager log -2 --oneline --decorate
git status --short
Ожидаются только исправление процента, ваш коммит непосредственно после incident-tip и чистое состояние отслеживаемых файлов. Точное сообщение и значения автора не являются критерием успеха.
Запустите подготовленный тест на настоящей текущей программе:
python3 /opt/labex/quote-desk/check.py
Все случаи теперь проходят с кодом 0. Создайте расчёт покупателя:
python3 quote.py ../orders/gift.order
Ожидаются текущее описание кружки и приветствие, количество 3, FRIEND10, сумма товаров EUR 48.00, скидка EUR 4.80, итог EUR 43.20 и текущие сведения о самовывозе с субботним временем до 16:00.
Доставьте этот настоящий вывод в подготовленный каталог quotes. Как было показано, > сохраняет stdout в этом указанном файле; он не меняет заказ или программу:
python3 quote.py ../orders/gift.order > ../quotes/mug-gift.txt
cat ../quotes/mug-gift.txt
Прочитайте весь сохранённый расчёт, а не только его имя файла. Файл — пригодный для покупателя результат, а коммит делает исправление воспроизводимым.
Проверьте обычный заказ и более поздний товар, которые должны остаться пригодными для использования:
python3 quote.py ../orders/plain.order
python3 quote.py ../orders/new-item.order
Обычная кружка остаётся EUR 16.00. Два Trail pins с STUDENT5 имеют сумму товаров EUR 10.00, скидку EUR 0.50 и итог EUR 9.50. Оба расчёта сохраняют текущие приветствие и сведения о самовывозе. Проверка наблюдает настоящий текущий коммит, полное сохранённое дерево, поведение исторической границы и доставленный расчёт; она не оценивает протокол команд или ключевое слово в сообщении.
Резюме
Вы использовали обычный и ошибочный заказы для определения бизнес-теста, вручную классифицировали исторические версии и автоматизировали тот же поиск с помощью Git bisect. Вы отличили ссылку на первый плохой коммит от HEAD, проверили кандидата и его родителя, вернулись в main и создали коммит целевого исправления без потери более поздних обновлений магазина. Покупатель получил полный правильный расчёт.
Независимое испытание меняет купон, заказ покупателя и положение ошибки, используя те же предоставленные программу, правила и формат теста. Выбирайте по настоящим свидетельствам, а не копируйте смещение коммита.



