Unterschiede
Hier werden die Unterschiede zwischen zwei Versionen angezeigt.
| Beide Seiten der vorigen Revision Vorhergehende Überarbeitung Nächste Überarbeitung | Vorhergehende Überarbeitung | ||
| modul:m450:learningunits:lu16:behant_python [2025/10/23 08:10] – [Aufbau eines Behave-Projekts] kmaurizi | modul:m450:learningunits:lu16:behant_python [2025/10/23 09:34] (aktuell) – [Vergleich zu Unit Tests] kmaurizi | ||
|---|---|---|---|
| Zeile 1: | Zeile 1: | ||
| - | ====== Behaviour Driven Development (BDD) mit Behave | + | ====== |
| ===== Einführung ===== | ===== Einführung ===== | ||
| Zeile 16: | Zeile 16: | ||
| * Entwicklungsschritte von der Benutzerstory bis zum Test automatisieren | * Entwicklungsschritte von der Benutzerstory bis zum Test automatisieren | ||
| * Früh Feedback erhalten, ob das System das gewünschte Verhalten zeigt | * Früh Feedback erhalten, ob das System das gewünschte Verhalten zeigt | ||
| + | |||
| + | ---- | ||
| + | |||
| + | ===== Ausgangssituation: | ||
| + | Stell dir vor, du entwickelst eine kleine **Applikation**, | ||
| + | Diese App soll so getestet werden, dass auch **nicht-technische Personen** verstehen, was überprüft wird. | ||
| + | |||
| + | Das Ziel ist nicht, die App zu programmieren – sondern **ihr Verhalten zu beschreiben und zu testen**, wie sie sich aus Sicht der Benutzer: | ||
| ---- | ---- | ||
| ===== Aufbau eines Behave-Projekts ===== | ===== Aufbau eines Behave-Projekts ===== | ||
| - | Ein Behave-Projekt | + | Ein Behave-Projekt |
| - | ''' | + | |
| + | < | ||
| project/ | project/ | ||
| - | ├── features/ | + | |
| - | │ ├── calculator.feature | + | ├── features/ |
| - | │ └── steps/ | + | |
| - | │ └── calculator_steps.py | + | |
| - | ''' | + | |
| - | perl | + | </ |
| - | Code kopieren | + | |
| * **'' | * **'' | ||
| * **'' | * **'' | ||
| + | * Das App-Modul ('' | ||
| ---- | ---- | ||
| ===== Gherkin-Syntax ===== | ===== Gherkin-Syntax ===== | ||
| - | Gherkin ist eine einfache | + | Gherkin ist eine leicht lesbare |
| - | Jede Datei beschreibt | + | Jede Feature-Datei beschreibt **eine Funktionalität** oder **Benutzerstory**. |
| Beispiel: | Beispiel: | ||
| - | ```gherkin | + | < |
| Feature: Einfacher Taschenrechner | Feature: Einfacher Taschenrechner | ||
| - | Um einfache Rechnungen zu machen | + | Um einfache Rechnungen |
| Möchte ich zwei Zahlen addieren können | Möchte ich zwei Zahlen addieren können | ||
| Scenario: Zwei Zahlen addieren | Scenario: Zwei Zahlen addieren | ||
| - | Given ich habe 50 in den Rechner | + | Given ich habe 50 in die App eingegeben |
| - | And ich habe 70 in den Rechner | + | And ich habe 70 in die App eingegeben |
| - | When ich drücke addieren | + | When ich die Additionsfunktion ausführe |
| - | Then sollte das Ergebnis 120 auf dem Bildschirm | + | Then sollte das Ergebnis 120 auf dem Bildschirm |
| - | Schlüsselwörter: | + | </ |
| - | '' | + | **Schlüsselwörter: |
| + | * '' | ||
| + | * '' | ||
| + | * '' | ||
| + | * '' | ||
| + | * '' | ||
| + | * '' | ||
| - | '' | + | ---- |
| - | '' | + | ===== Schrittdefinitionen und getestete App ===== |
| + | <WRAP group> | ||
| - | '' | + | <WRAP half column> |
| + | **Feature Steps (Testcode)** | ||
| - | '' | + | <code python> |
| + | from behave import given, when, then | ||
| + | from app.calculator import Calculator | ||
| - | '' | + | @given('ich habe {zahl:d} in die App eingegeben') |
| + | def step_input_number(context, | ||
| + | # Erstellt (falls nötig) eine neue App-Instanz | ||
| + | if not hasattr(context, | ||
| + | context.calc = Calculator() | ||
| + | context.calc.enter_number(zahl) | ||
| - | ===== Schrittdefinitionen | + | @when('ich die Additionsfunktion ausführe' |
| - | Jeder Schritt im Feature wird mit einer Python-Funktion verknüpft. | + | def step_perform_add(context): |
| + | # Führt die gewünschte Operation aus | ||
| + | context.result = context.calc.add() | ||
| - | python | + | @then(' |
| - | Code kopieren | + | def step_verify_result(context, expected): |
| - | from behave import given, when, then | + | # Überprüft das sichtbare Resultat der App |
| + | assert context.result == expected | ||
| + | </ | ||
| - | @given(' | + | </ |
| - | def step_eingabe(context, | + | |
| - | if not hasattr(context, | + | |
| - | context.zahlen = [] | + | |
| - | context.zahlen.append(zahl) | + | |
| - | @when(' | + | <WRAP half column> |
| - | def step_add(context): | + | **App-Code |
| - | | + | |
| - | @then(' | + | <code python> |
| - | def step_pruefen(context, | + | # app/ |
| - | assert context.resultat == erwartet | + | |
| - | Wichtig: | + | |
| - | Der '' | + | class Calculator: |
| + | def __init__(self): | ||
| + | # interner Speicher | ||
| + | self.numbers = [] | ||
| - | Parameter in geschweiften Klammern | + | def enter_number(self, |
| + | # Zahl zur Eingabeliste hinzufügen | ||
| + | self.numbers.append(value) | ||
| + | |||
| + | def add(self): | ||
| + | # Beispiel-Implementierung: | ||
| + | result = sum(self.numbers) | ||
| + | # leert Eingaben für nächsten Vorgang | ||
| + | self.numbers.clear() | ||
| + | return result | ||
| + | </ | ||
| + | |||
| + | </ | ||
| + | </ | ||
| + | |||
| + | **Hinweise: | ||
| + | * Das Modul '' | ||
| + | * Die Datei '' | ||
| + | * Der '' | ||
| + | * Jeder '' | ||
| ===== Tests ausführen ===== | ===== Tests ausführen ===== | ||
| - | Im Terminal | + | Im Terminal: |
| - | nginx | + | < |
| - | Code kopieren | + | |
| behave | behave | ||
| - | Ergebnis: | + | </ |
| - | vbnet | + | Ergebnis (Auszug): |
| - | Code kopieren | + | |
| + | < | ||
| Feature: Einfacher Taschenrechner | Feature: Einfacher Taschenrechner | ||
| Scenario: Zwei Zahlen addieren | Scenario: Zwei Zahlen addieren | ||
| - | Given ich habe 50 in den Rechner | + | Given ich habe 50 in die App eingegeben |
| - | And ich habe 70 in den Rechner | + | And ich habe 70 in die App eingegeben |
| - | When ich drücke addieren | + | When ich die Additionsfunktion ausführe |
| - | Then sollte das Ergebnis 120 auf dem Bildschirm | + | Then sollte das Ergebnis 120 auf dem Bildschirm |
| 1 feature passed, 0 failed | 1 feature passed, 0 failed | ||
| - | ===== Vorteile von Behave ===== | + | </ |
| - | Tests sind leicht lesbar für alle Beteiligten | + | ---- |
| - | Klarer Bezug zu Anforderungen / User Stories | + | ===== Vorteile von Behave ===== |
| + | * Tests sind **verständlich** für Entwickler: | ||
| + | * **Klarer Bezug** zu Anforderungen | ||
| + | * Schritte sind **wiederverwendbar** für mehrere Szenarien | ||
| + | * Einfach **automatisierbar** in CI/CD-Pipelines (z. B. GitHub Actions, Jenkins) | ||
| - | Wiederverwendbare Schritte in Python | + | ---- |
| - | + | ||
| - | Automatisierbar in CI/CD-Pipelines (z. B. GitHub Actions, Jenkins) | + | |
| ===== Vergleich zu Unit Tests ===== | ===== Vergleich zu Unit Tests ===== | ||
| + | ^ Aspekt ^ Unit Test ^ BDD (Behave) ^ | ||
| + | | Fokus | einzelne Funktion / Methode | Verhalten aus Nutzersicht | | ||
| + | | Sprache | Code (Python) | Gherkin (natürliche Sprache) | | ||
| + | | Zielgruppe | Entwickler: | ||
| + | | Beispiel | '' | ||
| - | Aspekt Unit Test BDD (Behave) | + | ---- |
| - | Fokus einzelne Funktion / Klasse Verhalten aus Nutzersicht | + | |
| - | Sprache Code (Python) Gherkin (natürliche Sprache) | + | |
| - | Zielgruppe Entwickler: | + | |
| - | Beispiel assert add(2, | + | |
| ===== Installation ===== | ===== Installation ===== | ||
| Installation mit '' | Installation mit '' | ||
| - | nginx | + | < |
| - | Code kopieren | + | |
| pip install behave | pip install behave | ||
| - | ===== Typische Fehlerquellen ===== | + | </ |
| - | Schrittdefinition fehlt oder Schreibweise weicht ab | + | ---- |
| - | Python-Datei liegt nicht im '' | + | ===== Typische Fehlerquellen ===== |
| + | * Schrittdefinition fehlt oder Schreibweise weicht ab | ||
| + | * Python-Datei liegt nicht im '' | ||
| + | * Context-Variable nicht initialisiert | ||
| + | * Feature-Datei hat keine Endung '' | ||
| - | Context-Variable nicht initialisiert | + | ---- |
| - | + | ||
| - | Feature-Datei hat keine Endung '' | + | |
| ===== Weiterführende Links ===== | ===== Weiterführende Links ===== | ||
| + | * Offizielle Dokumentation: | ||
| + | * Gherkin-Syntax Referenz: https:// | ||
| + | * Vergleich zu pytest-bdd: https:// | ||
| - | Offizielle Dokumentation: | + | ---- |
| - | + | {{tag> | |
| - | Gherkin-Syntax Referenz: | + | [[https://creativecommons.org/licenses/by-nc-sa/4.0/|{{https://i.creativecommons.org/l/by-nc-sa/ |
| - | + | ||
| - | Vergleich zu pytest-bdd: | + | |
| - | + | ||
| - | ===== Aufgabe (optional) ===== | + | |
| - | Erstelle ein eigenes Feature: | + | |
| - | + | ||
| - | Erstelle eine Datei '' | + | |
| - | + | ||
| - | Beschreibe ein Verhalten zum Umrechnen von Celsius in Fahrenheit | + | |
| - | + | ||
| - | Implementiere die Schrittdefinitionen in Python | + | |
| - | + | ||
| - | Führe die Tests mit '' | + | |
| - | + | ||
| - | yaml | + | |
| - | Code kopieren | + | |
| - | + | ||
| - | --- | + | |
| - | Möchtest du, dass ich daraus gleich noch eine **zweite DokuWiki-Seite für pytest-bdd** (Alternative mit pytest) erstelle, damit du sie als Vergleich oder Ergänzung in deinem Unterricht einsetzen kannst? | ||