Einführung
Little Pine Goods erstellt Preisangebote zur Abholung kleiner Geschenke. Ein Kunde meldet, dass das Angebot FRIEND10 nicht mehr den versprochenen Rabatt gewährt. Der jüngere Verlauf enthält außerdem nützliche Aktualisierungen an Produkten, Formulierungen und Abholinformationen. Den gesamten Shop auf eine alte Version zurückzusetzen würde daher gültige Arbeit verlieren.
Führe eine normale Bestellung und die fehlerhafte Geschenkbestellung aus und verwende dann einen vorbereiteten deterministischen fachlichen Test, um alte Versionen einzustufen. Übe zunächst etwas manuelle Git-Bisektion, bevor derselbe Test die Suche automatisiert. Vergleiche den ersten fehlerhaften Snapshot mit seinem direkten Vorgänger, verlasse die Suche und repariere den aktuellen Shop, während du die späteren Aktualisierungen erhältst. Liefere neben dem Korrektur-Commit auch eine vollständige Angebotsdatei für den Kunden.
Vorausgesetzt werden grundlegende Terminalnavigation, Commits, Branches und das Lesen einfacher Log-/Diff-Ausgaben. Git bisect, vorübergehende Checkouts mit losgelöstem HEAD, Test-Exit-Status und die kleine Änderung der Angebotsdatei werden hier erklärt. Python und das Angebotsprogramm sind vorbereitet; du führst sie aus, ohne Python zu schreiben. Dies ist ein echter lokaler Git-Verlauf mit einem dateibasierten Angebotswerkzeug auf einem einzigen Übungsrechner, mit fiktiven Bestellungen und Preisen in EUR. Eine Website, ein gehostetes Konto oder ein Netzwerkdeployment sind nicht nötig. Verwende das standardmäßige Terminal. Die Dauer von 50 Minuten ist eine Schätzung des Autors.
Das erste fehlerhafte Preisangebot finden
In diesem Schritt bestimmst du das korrekte fachliche Ergebnis, testest echte historische Snapshots und findest die Grenze, an der der Rabatt falsch wurde.
Beginne in Terminal und wechsle in das Shop-Repository:
cd /home/labex/project/quote-desk/shop
cd ändert das Verzeichnis dieses Terminals. Falls du einen Pfad falsch schreibst, gib mit pwd deinen Standort und mit ls den Inhalt dieses Verzeichnisses aus. Wiederhole dann den vollständigen cd-Befehl oben. Gewöhnliche Navigationsfehler erfordern kein Zurücksetzen der VM.
Lies die Kundenanfrage. cat zeigt eine Textdatei; .. bezeichnet das übergeordnete Verzeichnis:
cat ../request.txt
FRIEND10 verspricht 10% Rabatt auf die Artikelsumme. Es gibt weder Versandkosten noch Steuern. Die Geschenkbestellung umfasst drei Campingbecher zu je EUR 16.00: Zwischensumme EUR 48.00, Rabatt EUR 4.80, Gesamtbetrag EUR 43.20. Der vorhandene Katalog, die Bestellung und die Richtlinie sind die fachlichen Fakten; ändere sie nicht, um sie an ein fehlerhaftes Ergebnis anzupassen.
Führe zuerst eine normale Bestellung aus. python3 startet das bereitgestellte Programm quote.py; sein nächstes Argument ist die vorbereitete Bestelldatei. Du musst den Python-Quelltext weder bearbeiten noch verstehen:
python3 quote.py ../orders/plain.order
Die Bestellung eines Bechers verwendet den Gutschein NONE. Erwarte eine Zwischensumme und einen Gesamtbetrag von EUR 16.00, einen Rabatt von EUR 0.00, die aktuelle Begrüßungszeile und die Abholung am Samstag bis 16:00. Das zeigt ein nutzbares normales Preisangebot.
Führe die gemeldete Bestellung aus:
python3 quote.py ../orders/gift.order
Um den nativen Exit-Status des letzten Befehls zu lesen, verwende den Shell-Wert $?. echo gibt diesen Wert aus. Führe dies unmittelbar nach dem Angebotsbefehl aus:
echo $?
Erwarte 0: Das Programm lief erfolgreich, obwohl das finanzielle Ergebnis falsch ist.
Das Programm läuft, aber das Preisangebot ist falsch: Rabatt EUR 0.48 und Gesamtbetrag EUR 47.52. Ein erfolgreicher Programmabschluss ist etwas anderes als eine korrekte fachliche Antwort.
Der vorbereitete Test liegt außerhalb des Repositories, damit das Auschecken alter Versionen ihn nicht ersetzen kann. Er führt das tatsächliche Angebotsprogramm für mehrere Mengen und einen Kontrollfall ohne Gutschein aus und vergleicht die vollständigen Ergebnisse mit der unveränderten Angebotsrichtlinie. Führe ihn aus:
python3 /opt/labex/quote-desk/check.py
Lies sofort den Status dieses Tests mit demselben Shell-Wert:
echo $?
Erwarte 1: Dieser Test erkennt die fachliche Abweichung.
Erwarte FAIL-Zeilen für FRIEND10 und einen nativen Exit-Status von 1. Die NONE-Kontrollfälle bestehen. Der Test liefert 0 für korrekte Preisangebote, 1 für diesen fachlichen Fehler und 128, wenn er eine Version nicht testen kann. Kann eine Version nicht getestet werden, sollte die Suche anhalten, statt dies als Rabattregression zu erraten. Dieser vorbereitete Verlauf enthält weder Build-Fehler noch übersprungene Versionen.
Prüfe den aktuellen Branch und den sauberen Zustand. branch --show-current gibt den Branch aus; --short erzeugt eine kompakte Dateiliste:
git branch --show-current
git status --short
Erwarte main und keine Ausgabe geänderter Dateien. Halte den Shop während der Suche sauber. Lies seinen Verlauf: --no-pager gibt die Ausgabe direkt aus, statt ein Anzeigeprogramm zum Blättern zu öffnen, --oneline verkürzt Einträge und --decorate beschriftet Branches und Tags:
git --no-pager log --oneline --decorate
Der feste Tag incident-tip markiert die übernommene aktuelle Spitze, und known-good markiert die frühere funktionierende Version. Commit-Betreffzeilen beschreiben Arbeit, aber ihr Wortlaut ist kein Beweis dafür, wann das Preisangebot fehlerhaft wurde. Erhalte beide Tags und alle übernommenen Commits.
Die Testoption --revision führt den ausgewählten committeten Snapshot in einem vorübergehenden isolierten Verzeichnis aus, ohne deinen Checkout zu ändern oder zu reparieren. Bestimme beide Grenzen anhand des echten Verhaltens:
python3 /opt/labex/quote-desk/check.py --revision known-good
python3 /opt/labex/quote-desk/check.py --revision incident-tip
Der erste Befehl muss mit Status 0 bestehen. Der zweite muss mit Status 1 fehlschlagen. Eine korrekte Version und eine spätere fehlerhafte Version begrenzen die Suche. In dieser Übung wird der Fehler innerhalb dieses Intervalls einmal eingeführt und später nicht behoben.
Zwei Versionen von Hand einstufen
Git bisect grenzt dieses Intervall ein, indem es Versionen zwischen den Grenzen testet. Beginne mit der bekannten fehlerhaften Revision als erstem und der bekannten korrekten Revision als zweitem Argument:
git bisect start incident-tip known-good
Git checkt einen mittleren Snapshot aus und zeigt das verbleibende Intervall. Während der Suche bedeutet detached HEAD, dass du direkt einen Commit betrachtest, statt main weiterzubewegen. Bearbeite oder committe in diesen vorübergehenden Versionen nichts.
Führe denselben Test auf diesem ausgecheckten Snapshot aus:
python3 /opt/labex/quote-desk/check.py
Diese vorbereitete erste Auswahl schlägt mit Status 1 fehl. Stufe die beobachtete Version als fehlerhaft ein; bad beschreibt das fachliche Testergebnis, nicht ihre Commit-Nachricht:
git bisect bad
Git wählt einen anderen Snapshot aus. Teste ihn, statt zu raten:
python3 /opt/labex/quote-desk/check.py
Diese Auswahl besteht mit Status 0. Halte diese Beobachtung fest:
git bisect good
Git grenzt das Intervall erneut ein. Du hast gesehen, wie jedes Ergebnis einen Teil des Suchraums ausschließt. Um den automatischen Weg mit denselben ursprünglichen Grenzen zu üben, verlasse zuerst diese unvollständige Suche. bisect reset löscht den Suchzustand und kehrt zu dem Branch und der Revision zurück, wo die Suche begann; es macht keine Commits rückgängig:
git bisect reset
git branch --show-current
Erwarte main. Falls du beim Üben eine Version falsch einstufst, kannst du mit demselben Reset und einem neuen Start die Suche anhand der tatsächlichen Testergebnisse wiederholen, ohne Dateien zu verwerfen.
Den Test die Suche steuern lassen
Starte erneut und übergib dann bisect run denselben vollständigen Testbefehl. Git verwendet jeden nativen Exit-Status, um automatisch zwischen korrekt und fehlerhaft zu entscheiden:
git bisect start incident-tip known-good
git bisect run python3 /opt/labex/quote-desk/check.py
Erwarte mehrere Testläufe und eine Zeile, die mit is the first bad commit endet. Der Suchbefehl selbst endet mit Status 0, wenn er die Grenze erfolgreich findet, obwohl einzelne Angebotstests fehlgeschlagen sind. Commit-IDs können abweichen.
Die Git-Referenz bisect/bad zeigt auf den gefundenen ersten fehlerhaften Commit. Der aktuelle HEAD kann weiterhin die zuletzt getestete korrekte Version sein; nimm nicht an, dass er das gemeldete Ergebnis ist. Lies den tatsächlichen Kandidaten-Patch. show wählt diesen Commit und seinen Patch aus; -- trennt den Dateipfad ab:
git --no-pager show bisect/bad -- discounts.txt
Der FRIEND10-Prozentsatz wurde von 10 auf 1 geändert. Prüfe beide Seiten mit dem externen Test. Ein angehängtes ^ wählt den einzelnen direkten ersten Vorgänger eines Commits aus. bisect/bad^ ist also die Version unmittelbar vor dem Kandidaten, kein ganzer Bereich:
python3 /opt/labex/quote-desk/check.py --revision bisect/bad
python3 /opt/labex/quote-desk/check.py --revision bisect/bad^
Erwarte, dass der Kandidat mit Status 1 fehlschlägt und sein Vorgänger mit Status 0 besteht. Die Werte und das echte Verhalten stimmen überein. Lasse die abgeschlossene Suche für diesen Prüfpunkt offen; als Nächstes kehrst du vor dem Bearbeiten zum aktuellen Shop zurück.
Den aktuellen Shop reparieren und das Preisangebot liefern
In diesem Schritt verlässt du die historische Suche, committest eine gezielte Korrektur auf dem aktuellen Branch und lieferst ein vollständiges Preisangebot, ohne spätere Produkte oder Abholinformationen zu verlieren.
Bleibe in Terminal, in /home/labex/project/quote-desk/shop. Kehre mit dem bereits erklärten Zurücksetzen der Suche zum ursprünglichen Branch zurück:
git bisect reset
git branch --show-current
git --no-pager log -1 --oneline --decorate
git status --short
Erwarte main, die mit incident-tip markierte übernommene Spitze und keine Ausgabe geänderter Dateien. Die Log-Option -1 begrenzt die Ausgabe auf den neuesten Commit. Repariere keine losgelöste historische Version und ersetze nicht den gesamten Shop durch known-good: Spätere gültige Arbeit gehört zum Ergebnis.
Lies die kleine Angebotsdatei und die aktuellen Details, die du erhalten musst:
cat discounts.txt
cat welcome.txt pickup.txt care.txt
cat catalog.json
Der aktuelle Dateibaum enthält den Trail pin, die neue Begrüßungszeile und die Abholung am Samstag bis 16:00. Nur der Prozentsatz von FRIEND10 ist falsch. Die Angebotsdatei enthält pro Zeile eine Einstellung im Format CODE=integer-percent; TRAIL15 bleibt 15 und STUDENT5 bleibt 5.
Ersetze nur diese kleine Datei. printf gibt Werte anhand eines Formats aus: %s steht für Text, und \n fügt nach jedem übergebenen Wert einen Zeilenumbruch hinzu. Einfache Anführungszeichen bewahren den wörtlichen Text. > schreibt die Ausgabe in die benannte Datei und ersetzt nur diese Datei:
printf '%s\n' 'FRIEND10=10' 'TRAIL15=15' 'STUDENT5=5' > discounts.txt
Prüfe die tatsächliche Korrektur. Ein einfacher Diff vergleicht Arbeitsdateien mit dem Index, dem Staging-Bereich von Git:
git --no-pager diff -- discounts.txt
Erwarte ausschließlich, dass FRIEND10 von 1 zurück auf 10 geändert wird. Lege vor dem Speichern der Reparatur eine repository-lokale Commit-Identität fest. --local verhindert globale Konfiguration; Anführungszeichen halten einen Namen mit Leerzeichen zusammen. Diese fiktiven Beispiele kannst du ersetzen:
git config --local user.name "Little Pine Maintainer"
git config --local user.email "maintainer@little-pine.example"
Merke diese Datei mit add vor. Prüfe den vorgemerkten Patch mit --cached, das den Index mit dem aktuellen Commit vergleicht:
git add discounts.txt
git --no-pager diff --cached -- discounts.txt
Committe die gezielte Korrektur. -m übergibt direkt eine aussagekräftige Nachricht:
git commit -m "Restore the promised FRIEND10 discount"
Vergleiche mit der festen übernommenen Spitze. Dies ist ein neuer Korrektur-Commit, der jeden ursprünglichen Commit erhält, statt den Verlauf umzuschreiben:
git --no-pager diff incident-tip HEAD
git --no-pager log -2 --oneline --decorate
git status --short
Erwarte nur die Prozentkorrektur, deine Reparatur unmittelbar nach incident-tip und einen sauberen Zustand der versionierten Dateien. Der genaue Wortlaut der Nachricht und die Autorenwerte sind nicht das Erfolgskriterium.
Führe den vorbereiteten Test auf dem tatsächlichen aktuellen Programm aus:
python3 /opt/labex/quote-desk/check.py
Alle Fälle bestehen jetzt mit Status 0. Erzeuge das Preisangebot für den Kunden:
python3 quote.py ../orders/gift.order
Erwarte die aktuelle Becherbeschreibung und Begrüßungszeile, die Menge 3, FRIEND10, eine Zwischensumme von EUR 48.00, einen Rabatt von EUR 4.80, einen Gesamtbetrag von EUR 43.20 und die aktuelle Abholung bis Samstag 16:00.
Liefere diese echte Ausgabe in das vorbereitete Verzeichnis quotes. Wie gelernt speichert > stdout in dieser benannten Datei; es ändert weder die Bestellung noch das Programm:
python3 quote.py ../orders/gift.order > ../quotes/mug-gift.txt
cat ../quotes/mug-gift.txt
Lies das vollständige gespeicherte Preisangebot, nicht nur seinen Dateinamen. Die Datei ist das nutzbare Ergebnis für den Kunden, während der Commit die Reparatur wiederholbar macht.
Prüfe die normale Bestellung und das spätere Produkt, die nutzbar bleiben müssen:
python3 quote.py ../orders/plain.order
python3 quote.py ../orders/new-item.order
Der Becher ohne Gutschein bleibt bei EUR 16.00. Zwei Trail pins mit STUDENT5 haben eine Zwischensumme von EUR 10.00, einen Rabatt von EUR 0.50 und einen Gesamtbetrag von EUR 9.50. Beide behalten die aktuellen Begrüßungs- und Abholdetails bei. Der Prüfpunkt beobachtet den tatsächlichen aktuellen Commit, den vollständig erhaltenen Dateibaum, das Verhalten an der historischen Fehlergrenze und das gelieferte Preisangebot; er bewertet weder ein Befehlsprotokoll noch ein Schlüsselwort in einer Nachricht.
Zusammenfassung
Du hast normale und fehlerhafte Bestellungen verwendet, um einen fachlichen Test festzulegen, historische Versionen manuell eingestuft und dieselbe Suche mit Git bisect automatisiert. Du hast die Referenz auf den ersten fehlerhaften Commit von HEAD unterschieden, den Kandidaten und seinen direkten Vorgänger überprüft, bist zu main zurückgekehrt und hast eine gezielte Reparatur committet, ohne spätere Shop-Aktualisierungen zu verlieren. Der Kunde erhielt ein vollständiges korrektes Preisangebot.
Die unabhängige Challenge ändert den Gutschein, die Kundenbestellung und die Fehlerposition und verwendet dabei dasselbe bereitgestellte Programm, dieselbe Richtlinie und dasselbe Testformat. Wähle anhand der tatsächlichen Belege aus, statt einen Commit-Abstand zu kopieren.



