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:12] – 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 ===== | ||
| - | **Behaviour Driven Development (BDD)** ist eine Weiterentwicklung von **Test Driven Development (TDD)**. | + | **Behaviour Driven Development (BDD)** ist eine Weiterentwicklung von **Test Driven Development (TDD)**. |
| - | Beim BDD steht das **Verhalten eines Systems aus Sicht der Benutzer: | + | Beim BDD steht das **Verhalten eines Systems aus Sicht der Benutzer: |
| Tests werden in einer **natürlichen Sprache** formuliert, die von allen verstanden wird — nicht nur von Programmierer: | Tests werden in einer **natürlichen Sprache** formuliert, die von allen verstanden wird — nicht nur von Programmierer: | ||
| - | Ein populäres Framework für BDD in Python ist **'' | + | Ein populäres Framework für BDD in Python ist **'' |
| Damit lassen sich **lesbare Akzeptanztests** in einer sogenannten **Gherkin-Syntax** schreiben und mit Python-Code verknüpfen. | Damit lassen sich **lesbare Akzeptanztests** in einer sogenannten **Gherkin-Syntax** schreiben und mit Python-Code verknüpfen. | ||
| - | --- | + | ---- |
| ===== Ziel von BDD ===== | ===== Ziel von BDD ===== | ||
| + | * Verständliche Tests schreiben, die auch Fachpersonen lesen können | ||
| + | * Anforderungen und Tests in einer gemeinsamen Sprache beschreiben | ||
| + | * Entwicklungsschritte von der Benutzerstory bis zum Test automatisieren | ||
| + | * Früh Feedback erhalten, ob das System das gewünschte Verhalten zeigt | ||
| - | * Verständliche Tests schreiben, die auch Fachpersonen lesen können | + | ---- |
| - | * Anforderungen und Tests in einer gemeinsamen Sprache beschreiben | + | |
| - | * Entwicklungsschritte von der Benutzerstory bis zum Test automatisieren | + | |
| - | * 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/ | ||
| - | | + | ├── app/ < |
| + | ├── features/ | ||
| | | ||
| | | ||
| | | ||
| - | ``` | + | </ |
| - | * **'' | + | |
| - | * **'' | + | * **'' |
| + | * 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> | ||
| - | ===== Schrittdefinitionen (Step Definitions) ===== | + | <WRAP half column> |
| - | Jeder Schritt im Feature | + | **Feature |
| - | ```python | + | < |
| from behave import given, when, then | from behave import given, when, then | ||
| + | from app.calculator import Calculator | ||
| - | @given(' | + | @given(' |
| - | def step_eingabe(context, zahl): | + | def step_input_number(context, zahl): |
| - | if not hasattr(context, | + | # Erstellt (falls nötig) eine neue App-Instanz |
| - | context.zahlen | + | if not hasattr(context, |
| - | context.zahlen.append(zahl) | + | context.calc = Calculator() |
| + | context.calc.enter_number(zahl) | ||
| - | @when(' | + | @when(' |
| - | def step_add(context): | + | def step_perform_add(context): |
| - | context.resultat | + | # Führt die gewünschte Operation aus |
| + | context.result | ||
| - | @then(' | + | @then(' |
| - | def step_pruefen(context, | + | def step_verify_result(context, |
| - | assert context.resultat | + | # Überprüft das sichtbare Resultat der App |
| - | ``` | + | assert context.result |
| + | </ | ||
| - | **Wichtig: | + | </ |
| - | * Der '' | + | <WRAP half column> |
| - | * Parameter in geschweiften Klammern '' | + | **App-Code |
| - | --- | + | <code python> |
| + | # app/ | ||
| + | |||
| + | class Calculator: | ||
| + | def __init__(self): | ||
| + | # interner Speicher für eingegebene Zahlen | ||
| + | self.numbers = [] | ||
| + | |||
| + | 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: |
| - | ``` | + | < |
| behave | behave | ||
| - | ``` | + | </ |
| - | Ergebnis: | + | Ergebnis |
| - | ``` | + | < |
| 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 ===== | ===== Vorteile von Behave ===== | ||
| + | * Tests sind **verständlich** für Entwickler: | ||
| + | * **Klarer Bezug** zu Anforderungen oder Benutzerstories | ||
| + | * Schritte sind **wiederverwendbar** für mehrere Szenarien | ||
| + | * Einfach **automatisierbar** in CI/ | ||
| - | * Tests sind **leicht lesbar** für alle Beteiligten | + | ---- |
| - | * **Klarer Bezug** zu Anforderungen / User Stories | + | |
| - | * **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 | + | ---- |
| - | | ---------- | -------------------------- | -------------------------------------------------------------- | | + | |
| - | | Fokus | einzelne Funktion / Klasse | Verhalten aus Nutzersicht | + | |
| - | | Sprache | + | |
| - | | Zielgruppe | Entwickler: | + | |
| - | | Beispiel | + | |
| - | + | ||
| - | --- | + | |
| ===== Installation ===== | ===== Installation ===== | ||
| Installation mit '' | Installation mit '' | ||
| - | ``` | + | < |
| pip install behave | pip install behave | ||
| - | ``` | + | </ |
| - | --- | + | ---- |
| ===== Typische Fehlerquellen ===== | ===== Typische Fehlerquellen ===== | ||
| + | * Schrittdefinition fehlt oder Schreibweise weicht ab | ||
| + | * Python-Datei liegt nicht im '' | ||
| + | * Context-Variable nicht initialisiert | ||
| + | * Feature-Datei hat keine Endung '' | ||
| - | * Schrittdefinition fehlt oder Schreibweise weicht ab | + | ---- |
| - | * Python-Datei liegt nicht im '' | + | |
| - | * 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: | + | ---- |
| - | * Gherkin-Syntax Referenz: | + | {{tag> |
| - | * Vergleich zu pytest-bdd: [https://pytest-bdd.readthedocs.io](https://pytest-bdd.readthedocs.io) | + | [[https://creativecommons.org/licenses/by-nc-sa/4.0/|{{https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png}}]] |
| - | + | ||
| - | --- | + | |
| - | + | ||
| - | ===== Aufgabe (optional) ===== | + | |
| - | Erstelle ein eigenes Feature: | + | |
| - | + | ||
| - | 1. Erstelle eine Datei '' | + | |
| - | 2. Beschreibe ein Verhalten zum Umrechnen von Celsius in Fahrenheit | + | |
| - | 3. Implementiere die Schrittdefinitionen in Python | + | |
| - | 4. Führe die Tests mit '' | + | |