diff --git a/00_fehlersuche_und_grundlagen/README.md b/00_fehlersuche_und_grundlagen/README.md new file mode 100644 index 0000000..2b4ff34 --- /dev/null +++ b/00_fehlersuche_und_grundlagen/README.md @@ -0,0 +1,53 @@ +# Vorkapitel 00: Python Fehlersuche & Grundlagen 🔍🕵️‍♀️ + +Herzlich willkommen zum Warm-up! + +Bevor wir mit Klassen und objektorientierter Programmierung starten, lernen wir das wichtigste Handwerkszeug jeder guten Entwicklerin: **Wie man Fehler im Code schnell findet und behebt.** + +--- + +## 💡 Fehlermeldungen richtig lesen: Die Unten-nach-Oben-Regel + +Wenn Python stoppt und einen roten Text anzeigt, nennt man das einen **Traceback**. +Lies immer ganz unten: + +```text +Traceback (most recent call last): + File "aufgabe.py", line 15, in + summe = punkte + bonus +TypeError: unsupported operand type(s) for +: 'int' and 'str' +``` +1. **Ganz unten:** Was ist das Problem? (`TypeError: ... 'int' and 'str'`) +2. **Zeile darüber:** Wo ist es passiert? (`line 15`) + +--- + +## 🚫 Die 4 häufigsten Python-Fehler + +1. **`IndentationError`:** + In Python müssen Codeblöcke in Funktionen, Bedingungen und Schleifen **genau 4 Leerzeichen** eingerückt sein. +2. **`SyntaxError`:** + Doppelpunkte am Ende von `def`, `if`, `else`, `for` vergessen oder ungeschlossene Klammern `)`. +3. **`NameError`:** + Tippfehler beim Namen einer Variable oder Funktion (z.B. `spielr_name` statt `spieler_name`). +4. **`TypeError`:** + Falsche Datentypen gemischt (z.B. `"Ergebnis: " + 10` statt `f"Ergebnis: {10}"`). + +--- + +## 🎯 Deine Detektiv-Aufgabe in `aufgabe.py` + +In `aufgabe.py` hat sich ein fehlerhaftes Quiz-Programm eingeschlichen. Deine Aufgabe ist es, die 5 versteckten Fehler zu finden und zu reparieren. + +### Vorgehen: +1. Führe die Datei im Terminal aus: + ```bash + python3 aufgabe.py + ``` +2. Lies die Fehlermeldung von unten nach oben. +3. Behebe den ersten angezeigten Fehler. +4. Wiederhole die Schritte, bis das Skript ohne Fehler durchläuft! +5. Führe den Test zur Bestätigung aus: + ```bash + python3 test_aufgabe.py + ``` diff --git a/00_fehlersuche_und_grundlagen/aufgabe.py b/00_fehlersuche_und_grundlagen/aufgabe.py new file mode 100644 index 0000000..6552689 --- /dev/null +++ b/00_fehlersuche_und_grundlagen/aufgabe.py @@ -0,0 +1,76 @@ +""" +Vorkapitel 00: Python-Detektivin – Finde die 5 versteckten Fehler! +================================================================== + +In diesem Skript haben sich 5 typische Python-Fehler eingeschlichen. +Führe das Skript mit 'python3 aufgabe.py' aus, lies die Fehlermeldungen +und behebe die Fehler der Reihe nach von BUG 1 bis BUG 5. +""" + +# ============================================================================== +# BUG 1 & BUG 2: SyntaxError & IndentationError +# In dieser Funktion fehlen ein Doppelpunkt ':' und die Einrückung stimmt nicht! +# ============================================================================== +def berechne_endstand(basis_punkte, bonus) + gesamt = basis_punkte + bonus + if bonus > 10: + gesamt += 5 # Hier ist ein Einrückungsfehler! + return gesamt + + +# ============================================================================== +# BUG 3: NameError +# Hier hat sich ein Tippfehler bei einem Variablennamen eingeschlichen! +# ============================================================================== +def punkte_multiplizieren(spieler_punkte, faktor): + # Finde den Tippfehler im Variablennamen: + ergebnis = spiler_punkte * faktor + return ergebnis + + +# ============================================================================== +# BUG 4: TypeError +# Hier wird versucht, eine Zahl und einen Text mit '+' zusammenzufügen. +# Tipp: Nutze stattdessen einen sauberen f-String: f"Spieler {name} hat {punkte} Punkte!" +# ============================================================================== +def formatierte_ausgabe(name, punkte): + text = "Spieler " + name + " hat " + punkte + " Punkte!" + return text + + +# ============================================================================== +# BUG 5: Logik-Fehler (Vergleichsoperator) +# Diese Funktion soll True zurückgeben, wenn ein Spieler 50 ODER MEHR Punkte hat. +# Aktuell gibt sie bei genau 50 Punkten leider False zurück! +# ============================================================================== +def ist_sieger(punkte): + if punkte > 50: + return True + else: + return False + + +# ============================================================================== +# Hauptprogramm zum Ausprobieren: +# (Führe dieses Skript aus mit: python3 aufgabe.py) +# ============================================================================== +if __name__ == "__main__": + print("🕵️‍♀️ --- CODE-DETEKTIVIN QUIZ TEST --- 🕵️‍♀️") + + # Test 1 + endstand = berechne_endstand(20, 15) + print(f"Endstand (sollte 40 sein): {endstand}") + + # Test 2 + multipliziert = punkte_multiplizieren(10, 3) + print(f"Multipliziert (sollte 30 sein): {multipliziert}") + + # Test 3 + ausgabe = formatierte_ausgabe("Mia", 50) + print(f"Formatierte Ausgabe: {ausgabe}") + + # Test 4 + sieger = ist_sieger(50) + print(f"Ist 50 Punkte ein Sieg? (sollte True sein): {sieger}") + + print("\n🎉 Herzlichen Glückwunsch! Alle 5 Bugs wurden erfolgreich behoben!") diff --git a/00_fehlersuche_und_grundlagen/index.html b/00_fehlersuche_und_grundlagen/index.html new file mode 100644 index 0000000..87e6534 --- /dev/null +++ b/00_fehlersuche_und_grundlagen/index.html @@ -0,0 +1,209 @@ + + + + + + Kapitel 00: Fehlersuche & Grundlagen + + + + +
+
+ +
Vorkapitel 00
+

Python Fehlersuche & Grundlagen 🔍🕵️‍♀️

+

Lerne, wie du Fehlermeldungen richtig liest, Einrückungsfehler behebst und Bugs wie eine echte Detektivin aufspürst.

+
+
+ +
+ + +
+

1. Die wichtigste Regel: Keine Panik bei Fehlern!

+ +

+ Jeder Programmierer auf der Welt – selbst bei Google oder Apple – schreibt täglich dutzende Fehler. +

+ +
+
💡 Der Computer ist dein Assistent, kein Richter:
+ Wenn Python eine rote Fehlermeldung (einen sogenannten Traceback) anzeigt, ist das nichts Schlimmes. Der Computer sagt dir damit nur: "Hey, hier verstehe ich in Zeile X etwas noch nicht ganz – kannst du mir kurz helfen?" +
+ +

Wie liest man einen Traceback? (Die Unten-nach-Oben-Regel)

+

+ Ein Traceback kann lang und einschüchternd wirken. Doch das Geheimnis ist: Lies immer ganz unten! +

+ +
+
+ Beispiel einer Fehlermeldung +
+
Traceback (most recent call last):
+  File "aufgabe.py", line 12, in berechne_rabatt
+    ergebnis = preis * rabatt_prozent
+TypeError: can't multiply sequence by non-int of type 'float'
+▲                                  ▲
+1. ART DES FEHLERS                 2. DIE ERKLÄRUNG
+
+ +

+ Ganz unten steht: +
1. Um welchen Fehler handelt es sich? (z.B. TypeError) +
2. Was genau ist schiefgelaufen? (z.B. Text mit Kommazahl multipliziert) +
3. Direkt in der Zeile darüber steht die Dateiname und Zeilennummer (z.B. line 12)! +

+
+ + +
+

2. Die 4 häufigsten Python-Fehler im Überblick

+ + +
+
1. IndentationError (Einrückungsfehler)
+

In Python haben Einrückungen eine feste Bedeutung. Alles, was in einer Funktion, Schleife oder Bedingung steht, muss genau 4 Leerzeichen eingerückt sein.

+
+ +
+
Vergleich: Einrückung
+
# ❌ Falsch:
+def begruessung(name):
+print("Hallo", name)  # 💥 IndentationError: expected an indented block
+
+# ✅ Richtig:
+def begruessung(name):
+    print("Hallo", name)  # 4 Leerzeichen eingerückt!
+
+ + +
+
2. SyntaxError (Tippfehler & fehlende Doppelpunkte)
+

Häufig vergessen: Der Doppelpunkt : am Ende von def, if, else, for oder while, oder eine ungeschlossene Klammer.

+
+ +
+
Vergleich: Syntax
+
# ❌ Falsch: Doppelpunkt vergessen
+if alter >= 18
+    print("Volljährig")  # 💥 SyntaxError: expected ':'
+
+# ✅ Richtig:
+if alter >= 18:
+    print("Volljährig")
+
+ + +
+
3. NameError (Unbekannter Name / Tippfehler)
+

Tritt auf, wenn eine Variable oder Funktion aufgerufen wird, die nicht existiert (oder falsch geschrieben wurde).

+
+ +
+
Vergleich: NameError
+
spieler_name = "Alex"
+print(spielr_name)  # 💥 NameError: name 'spielr_name' is not defined (Tippfehler!)
+
+ + +
+
4. TypeError (Falscher Datentyp)
+

Tritt auf, wenn man Operationen mit unpassenden Typen versucht (z.B. Zahl an Text anhängen mit + statt f-String).

+
+ +
+
Vergleich: TypeError
+
punkte = 100
+# ❌ Falsch:
+print("Du hast " + punkte + " Punkte!")  # 💥 TypeError: can only concatenate str to str
+
+# ✅ Richtig mit f-String:
+print(f"Du hast {punkte} Punkte!")
+
+
+ + +
+

3. 🕵️‍♀️ Deine Detektiv-Aufgabe in aufgabe.py

+ +

+ In der Datei 00_fehlersuche_und_grundlagen/aufgabe.py findest du ein kleines Programm für ein Quiz-Spiel, in dem sich 5 typische Fehler versteckt haben! +

+

Deine Mission als Code-Detektivin:

+ +
    +
  • + + +
  • +
  • + + +
  • +
  • + + +
  • +
  • + + +
  • +
  • + + +
  • +
+ +

💡 Lösungshinweise (Aufklappen bei Bedarf)

+ +
+ 🔍 Tipp zur Ausführung im Terminal +
+

Führe das Skript einfach direkt im Terminal aus:

+
+
python3 aufgabe.py
+
+

Python zeigt dir sofort den ersten Fehler an. Repariere ihn, führe das Skript erneut aus und arbeite dich so Schritt für Schritt durch!

+
+
+
+ + +
+

4. 🧪 Detektiv-Prüfung abschließen

+

Sobald du alle Fehler behoben hast, teste deine Lösung mit:

+
+
+ Terminal +
+
python3 test_aufgabe.py
+
+ + +
+ +
+ + + diff --git a/00_fehlersuche_und_grundlagen/musterloesung.py b/00_fehlersuche_und_grundlagen/musterloesung.py new file mode 100644 index 0000000..ba4a0ca --- /dev/null +++ b/00_fehlersuche_und_grundlagen/musterloesung.py @@ -0,0 +1,40 @@ +""" +Vorkapitel 00: Python-Detektivin – Musterlösung +============================================== +Hier ist die vollständig fehlerfreie Version des Skripts. +""" + +# BUG 1 & 2 behoben: Doppelpunkt hinzugefügt und 'gesamt += 5' sauber eingerückt: +def berechne_endstand(basis_punkte, bonus): + gesamt = basis_punkte + bonus + if bonus > 10: + gesamt += 5 + return gesamt + + +# BUG 3 behoben: Tippfehler 'spiler_punkte' -> 'spieler_punkte' korrigiert: +def punkte_multiplizieren(spieler_punkte, faktor): + ergebnis = spieler_punkte * faktor + return ergebnis + + +# BUG 4 behoben: f-String verwendet, um Zahl und Text sauber zu verbinden: +def formatierte_ausgabe(name, punkte): + text = f"Spieler {name} hat {punkte} Punkte!" + return text + + +# BUG 5 behoben: >= statt > verwendet: +def ist_sieger(punkte): + if punkte >= 50: + return True + else: + return False + + +if __name__ == "__main__": + print("🕵️‍♀️ --- CODE-DETEKTIVIN QUIZ TEST (Musterlösung) --- 🕵️‍♀️") + print("Endstand (40):", berechne_endstand(20, 15)) + print("Multipliziert (30):", punkte_multiplizieren(10, 3)) + print("Ausgabe:", formatierte_ausgabe("Mia", 50)) + print("Sieg bei 50:", ist_sieger(50)) diff --git a/00_fehlersuche_und_grundlagen/test_aufgabe.py b/00_fehlersuche_und_grundlagen/test_aufgabe.py new file mode 100644 index 0000000..9015efe --- /dev/null +++ b/00_fehlersuche_und_grundlagen/test_aufgabe.py @@ -0,0 +1,63 @@ +import unittest +import sys +import importlib +from pathlib import Path + +sys.path.insert(0, str(Path(__file__).parent)) + + +class TestKapitel00(unittest.TestCase): + + @classmethod + def setUpClass(cls): + # Wenn ein Test-Runner vorher 'aufgabe' durch ein anderes Modul ersetzt hat (z.B. musterloesung): + if hasattr(cls, "modul_name"): + cls.mod = importlib.import_module(cls.modul_name) + else: + try: + cls.mod = importlib.import_module("aufgabe") + except SyntaxError as e: + cls.mod = None + cls.import_error = f"SyntaxError in 'aufgabe.py': {e}. Überprüfe Doppelpunkte und Einrückungen!" + except Exception as e: + cls.mod = None + cls.import_error = f"Fehler beim Import von 'aufgabe.py': {e}" + + def _get_modul(self): + if getattr(self, "mod", None) is None: + err = getattr(self, "import_error", "aufgabe.py konnte nicht importiert werden") + self.fail(f"❌ {err}") + return self.mod + + def test_01_berechne_endstand(self): + """Prüft berechne_endstand (Syntax & Einrückung behoben).""" + mod = self._get_modul() + self.assertTrue(hasattr(mod, "berechne_endstand"), "Funktion 'berechne_endstand' fehlt!") + self.assertEqual(mod.berechne_endstand(20, 15), 40, "berechne_endstand(20, 15) sollte 40 sein (inkl. Bonus)!") + self.assertEqual(mod.berechne_endstand(20, 5), 25, "berechne_endstand(20, 5) sollte 25 sein!") + + def test_02_punkte_multiplizieren(self): + """Prüft punkte_multiplizieren (Tippfehler NameError behoben).""" + mod = self._get_modul() + self.assertTrue(hasattr(mod, "punkte_multiplizieren"), "Funktion 'punkte_multiplizieren' fehlt!") + self.assertEqual(mod.punkte_multiplizieren(10, 3), 30) + self.assertEqual(mod.punkte_multiplizieren(7, 2), 14) + + def test_03_formatierte_ausgabe(self): + """Prüft formatierte_ausgabe (TypeError behoben).""" + mod = self._get_modul() + self.assertTrue(hasattr(mod, "formatierte_ausgabe"), "Funktion 'formatierte_ausgabe' fehlt!") + ergebnis = mod.formatierte_ausgabe("Mia", 50) + self.assertEqual(ergebnis, "Spieler Mia hat 50 Punkte!") + + def test_04_ist_sieger_grenzwert(self): + """Prüft Logik von ist_sieger (>= 50 Punkte).""" + mod = self._get_modul() + self.assertTrue(hasattr(mod, "ist_sieger"), "Funktion 'ist_sieger' fehlt!") + self.assertTrue(mod.ist_sieger(50), "Fehler: Genau 50 Punkte müssen True (Sieg) ergeben (>= 50)!") + self.assertTrue(mod.ist_sieger(100), "100 Punkte müssen True ergeben!") + self.assertFalse(mod.ist_sieger(49), "49 Punkte dürfen noch kein Sieg sein (False)!") + + +if __name__ == "__main__": + unittest.main(verbosity=2) diff --git a/01_einstieg_klassen/index.html b/01_einstieg_klassen/index.html index 5aa6bae..9e3b1d6 100644 --- a/01_einstieg_klassen/index.html +++ b/01_einstieg_klassen/index.html @@ -13,6 +13,8 @@
Kapitel 01
@@ -278,7 +280,7 @@ diff --git a/README.md b/README.md index 8eb160d..b0fba49 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,7 @@ Die Übungen sind so aufgebaut, dass jedes Kapitel auf dem vorherigen aufbaut: | Kapitel | Thema | Was du lernst | | :--- | :--- | :--- | +| **[00. Fehlersuche & Grundlagen](./00_fehlersuche_und_grundlagen/)** | Warm-up & Debugging | Tracebacks lesen, Einrückungen (`IndentationError`), Typfehler & Detektiv-Aufgabe | | **[01. Einstieg in Klassen](./01_einstieg_klassen/)** | Warum Klassen? | Bauplan vs. Objekt, Instanziierung & Attribute | | **[02. Konstruktor & self](./02_init_und_self/)** | `__init__` & `self` | Objekte sauber mit Startwerten initialisieren | | **[03. Methoden & Verhalten](./03_methoden_und_verhalten/)** | Methoden & Interaktion | Objekte können handeln & miteinander interagieren | @@ -24,30 +25,28 @@ Die Übungen sind so aufgebaut, dass jedes Kapitel auf dem vorherigen aufbaut: ## 📁 Aufbau eines Kapitels In jedem Kapitelordner findest du: -1. **`README.md`**: Eine verständliche Erklärung mit Analogien aus dem Alltag und Codebeispielen. -2. **`aufgabe.py`**: Dein Arbeitsblatt! Hier steht der Starter-Code mit klaren `TODO`-Kommentaren. -3. **`test_aufgabe.py`**: Automatische Tests, mit denen du deine Lösung jederzeit überprüfen kannst. -4. **`musterloesung.py`**: Eine ausführlich kommentierte Beispiellösung (falls du mal nicht weiterkommst oder vergleichen möchtest). +1. **`index.html`**: Eine interaktive, schön gestaltete Webseite mit ausführlichen Erklärungen, Vollbeispielen und aufklappbaren Lösungshinweisen. +2. **`README.md`**: Die Erklärung im Markdown-Format. +3. **`aufgabe.py`**: Dein Arbeitsblatt! Hier steht der Starter-Code mit klaren `TODO`-Kommentaren. +4. **`test_aufgabe.py`**: Automatische Tests, mit denen du deine Lösung jederzeit überprüfen kannst. +5. **`musterloesung.py`**: Eine ausführlich kommentierte Beispiellösung. --- ## 🚀 Wie du vorgehst -1. Öffne den Ordner des aktuellen Kapitels (z.B. `01_einstieg_klassen`). -2. Lies dir die Erklärung in der jeweiligen `README.md` durch. -3. Öffne `aufgabe.py` und bearbeite die nummerierten `TODO`s. +1. Öffne den Ordner des aktuellen Kapitels (z.B. `00_fehlersuche_und_grundlagen`). +2. Öffne die `index.html` im Browser oder lies die `README.md`. +3. Öffne `aufgabe.py` und bearbeite die nummerierten `TODO`s / Bugs. 4. Führe die Tests aus, um deine Lösung zu prüfen: ```bash - # Aus dem Hauptverzeichnis: - python3 -m unittest 01_einstieg_klassen/test_aufgabe.py - - # Oder direkt im Ordner: - cd 01_einstieg_klassen python3 test_aufgabe.py ``` 5. Wenn alle Tests mit einem grünen `OK` durchlaufen: **Herzlichen Glückwunsch!** Du bist bereit für das nächste Kapitel! 🏆 --- -## 💡 Tipp zum Lernen -Versuche zuerst selbst eine Lösung zu finden. Wenn ein Fehler auftritt, lies die Fehlermeldung der Tests aufmerksam durch – sie gibt dir oft schon den entscheidenden Hinweis! Wenn du gar nicht weiterkommst, wirf einen Blick in `musterloesung.py` und versuche zu verstehen, wie das Problem gelöst wurde. +## 💡 Gesamten Fortschritt prüfen +```bash +python3 test_all.py +``` diff --git a/index.html b/index.html index 6578a55..34e7f69 100644 --- a/index.html +++ b/index.html @@ -26,26 +26,36 @@ Jetzt machen wir den nächsten großen Schritt in der Softwareentwicklung: Klassen & Objekte!

- Mit Klassen kannst du zusammengehörige Daten und Aktionen an einem Ort bündeln. Fast jede moderne App (ob Instagram, Spotify oder Computerspiele) basiert auf objektorientierter Programmierung. + Damit du beim Programmieren nie an kleinen Syntaxfehlern verzweifelst, starten wir mit einem kurzen Warm-up zur Fehlersuche (Kapitel 00), bevor es mit den Klassen losgeht.

-
🏗️ Die Grundidee in einem Satz:
+
🏗️ Die Grundidee von OOP in einem Satz:
Eine Klasse ist wie ein Bauplan (oder eine Plätzchen-Ausstechform). Ein Objekt ist das fertige Haus (oder das gebackene Plätzchen), das nach diesem Bauplan entstanden ist!
-

🗺️ Dein Lernpfad (Kapitel 01 bis 06)

+

🗺️ Dein Lernpfad (Kapitel 00 bis 06)

+ + +
+ Vorkapitel 00 +
🔍 Fehlersuche & Bugs
+
Tracebacks richtig lesen, Einrückungsfehler (IndentationError), Typfehler und eine interaktive Detektiv-Aufgabe.
+
+ +
+
Kapitel 01
🐶 Die erste Klasse
-
Was ist eine Klasse? Bauplan vs. Objekt, Instanziierung und erste Attribute am Haustier-Beispiel.
+
Was ist eine Klasse? Bauplan vs. Objekt, Instanziierung und erste Attribute am Haustier- & Fahrrad-Beispiel.
@@ -55,7 +65,7 @@
Kapitel 02
💳 Konstruktor & self
-
Wie __init__ Objekte startklar macht und was das Wörtchen self wirklich bedeutet (Bankkonto-App).
+
Wie __init__ Objekte startklar macht und was self bedeutet (Smartphone- & Bankkonto-App).
@@ -65,7 +75,7 @@
Kapitel 03
⚔️ Methoden & Verhalten
-
Objekte führen Aktionen aus! Interaktion zwischen Helden und Monstern in einem RPG-Kampfsimulator.
+
Objekte führen Aktionen aus! Interaktion zwischen Objekten in Rennautos und RPG-Heldenduellen.
@@ -75,7 +85,7 @@
Kapitel 04
🧾 Schöne Textausgabe
-
Wie man print(objekt) mit __str__ lesbar macht und Objekte im Warenkorb sammelt.
+
Wie man print(objekt) mit __str__ lesbar macht und Objekte im Warenkorb & bei Pizza-Bestellungen sammelt.
@@ -85,7 +95,7 @@
Kapitel 05
🎵 Komposition & Playlists
-
Objekte verwalten andere Objekte: Song-Suche, Längenberechnung und Filter in Spotify-Playlists.
+
Objekte verwalten andere Objekte: Song-Suche, Längenberechnung und Filter in Spotify-Playlists & Schulklassen.
@@ -107,9 +117,9 @@

🚀 Wie du vorgehst (Schritt-für-Schritt)

    -
  1. Wähle das nächste offene Kapitel aus der Liste oben.
  2. -
  3. Lies die Erklärungen und schau dir die Codebeispiele und „Stolperfallen“ an.
  4. -
  5. Öffne die aufgabe.py im entsprechenden Kapitelordner und löse die TODOs.
  6. +
  7. Wähle das nächste offene Kapitel aus der Liste oben (am besten startest du mit Kapitel 00).
  8. +
  9. Lies die Erklärungen und schau dir die vollständigen Codebeispiele an.
  10. +
  11. Öffne die aufgabe.py im entsprechenden Kapitelordner und löse die Aufgaben.
  12. Führe im Terminal den automatischen Test aus:
    diff --git a/test_all.py b/test_all.py index fcbb3c8..6d4ac61 100644 --- a/test_all.py +++ b/test_all.py @@ -11,6 +11,7 @@ import unittest from pathlib import Path KAPITEL = [ + ("Kapitel 00: Python-Fehlersuche (Warm-up)", "00_fehlersuche_und_grundlagen"), ("Kapitel 01: Einstieg in Klassen", "01_einstieg_klassen"), ("Kapitel 02: Konstruktor & self", "02_init_und_self"), ("Kapitel 03: Methoden & Verhalten", "03_methoden_und_verhalten"), @@ -21,9 +22,9 @@ KAPITEL = [ def main(): root = Path(__file__).parent.resolve() - print("=" * 60) + print("=" * 65) print("🎓 PYTHON OOP ÜBUNGSREIHE – GESAMTFORTSCHRITT") - print("=" * 60) + print("=" * 65) gesamt_bestanden = 0 @@ -42,31 +43,30 @@ def main(): runner = unittest.TextTestRunner(stream=open("/dev/null", "w"), verbosity=0) result = runner.run(suite) - # Modul aus sys.path und sys.modules entfernen für saubere Isolation + # Module für saubere Isolation entfernen if str(kapitel_pfad) in sys.path: sys.path.remove(str(kapitel_pfad)) - if "aufgabe" in sys.modules: - del sys.modules["aufgabe"] - if "test_aufgabe" in sys.modules: - del sys.modules["test_aufgabe"] + for m in list(sys.modules.keys()): + if m in ("aufgabe", "test_aufgabe", "musterloesung"): + del sys.modules[m] anzahl_tests = result.testsRun erfolgreich = result.wasSuccessful() and anzahl_tests > 0 if erfolgreich: - print(f" ✅ {titel:42s} ({anzahl_tests}/{anzahl_tests} Tests OK)") + print(f" ✅ {titel:45s} ({anzahl_tests}/{anzahl_tests} Tests OK)") gesamt_bestanden += 1 else: fehlgeschlagen = len(result.failures) + len(result.errors) - print(f" ⏳ {titel:42s} (Noch offen / {fehlgeschlagen} Fehler)") + print(f" ⏳ {titel:45s} (Noch offen / {fehlgeschlagen} Fehler)") - print("=" * 60) + print("=" * 65) print(f"Ergebnis: {gesamt_bestanden} von {len(KAPITEL)} Kapiteln vollständig gelöst!") if gesamt_bestanden == len(KAPITEL): - print("🏆 PERFEKT! Du hast alle OOP-Aufgaben mit Bravour gemeistert! 🎉") + print("🏆 PERFEKT! Du hast alle Aufgaben mit Bravour gemeistert! 🎉") else: print("💡 Öffne das nächste offene Kapitel und starte mit aufgabe.py!") - print("=" * 60) + print("=" * 65) if __name__ == "__main__":