Einführung in Software-Tests

In dieser Einführungslektion lernst du die wichtigsten Grundbegriffe und Konzepte des Software-Testens kennen. Du verstehst, welche Rolle Tests in der Softwareentwicklung spielen und wie sie zur Qualitätssicherung beitragen. Diese Grundlagen helfen dir dabei, systematisch an das Testen von Software heranzugehen und eine gemeinsame Fachsprache mit anderen Entwicklern zu nutzen.

Einführung

Am 4. Juni 1996 explodierte die Ariane-5-Rakete nur 37 Sekunden nach dem Start. Die Ursache: Ein Softwarefehler bei der Umwandlung einer 64-Bit-Gleitkommazahl in einen 16-Bit-Integer. Der Wert war zu groß. Die Steuerung interpretierte den Überlauf als Kurskorrektur und zerstörte die Rakete. Schaden: über 370 Millionen Dollar.

Wenn Software nicht getestet wird, können kleine Fehler katastrophale Folgen haben. Der Ariane-5-Bug war ein einziger fehlender Wertebereichs-Test.

Noch dramatischer: Die Boeing 737 MAX Abstürze 2018/2019 mit 346 Todesopfern. Ein fehlerhaftes Steuerungssystem (MCAS) drückte die Flugzeugnase nach unten, basierend auf einem einzelnen, fehlerhaften Sensor. Unzureichende Tests hatten das Problem nicht erkannt.

In dieser Lerneinheit erfährst du, was Software-Tests sind, welche grundlegenden Begriffe du kennen musst und warum systematisches Testen die Grundlage für zuverlässige Software bildet.

Lernziele

Nach dieser Lerneinheit kannst du:

  • Die wichtigsten Fachbegriffe des Software-Testens erklären (Testfall, Assertion, Bug, Test Suite)
  • Den Unterschied zwischen manuellen und automatisierten Tests beschreiben
  • Die Einordnung von Tests im SDLC verstehen und erklären, warum frühe Tests wichtig sind
  • Die Kosten-Nutzen-Abwägung von Tests einschätzen und die “Rule of 10” anwenden

Überleitung

Software-Tests sind systematische Verfahren, um die Qualität von Software zu prüfen und Fehler zu finden, bevor sie Schaden anrichten. In der modernen Softwareentwicklung sind Tests kein optionaler Schritt am Ende, sondern ein integraler Bestandteil des gesamten Entwicklungsprozesses.

Wir beginnen mit den grundlegenden Begriffen: Was ist ein Testfall? Was ist eine Assertion? Diese Fachsprache brauchst du, um in jedem Entwicklerteam mitzureden.

Was ist ein Testfall?

Ein Testfall (Test Case) ist eine konkrete Prüfsituation mit definierten Bedingungen. Er beschreibt:

  • Eingabewerte: Was wird der Software übergeben?
  • Ausführungsbedingungen: In welchem Zustand befindet sich das System?
  • Erwartetes Ergebnis: Was soll passieren?
  • Tatsächliches Ergebnis: Was passiert wirklich?

Ein guter Testfall ist wie ein Experiment: Du stellst eine Hypothese auf (“Wenn ich 2+2 eingebe, erwarte ich 4”) und prüfst sie.

Testfälle können manuell (von einem Menschen durchgeführt) oder automatisiert (von einem Programm ausgeführt) sein. In der Praxis kombiniert man beide Ansätze.

Die Assertion

Eine Assertion (Zusicherung) ist die zentrale Prüfung in jedem Testfall. Sie bestätigt, dass das tatsächliche Ergebnis dem erwarteten entspricht.

Schauen wir uns einen einfachen Test in Python an:

def addiere(a, b):
    return a + b
 
def test_addition():
    ergebnis = addiere(2, 2)
    assert ergebnis == 4  # Assertion: Ergebnis muss 4 sein

Erklärung des Codes

Die Funktion addiere(a, b):

Dies ist die Funktion, die wir testen wollen. Sie nimmt zwei Parameter und gibt deren Summe zurück.

Die Testfunktion test_addition():

ergebnis = addiere(2, 2)

Wie funktioniert das? Wir rufen die Funktion addiere mit den Werten 2 und 2 auf und speichern das Ergebnis in einer Variable.

assert ergebnis == 4

Wie funktioniert das? Das Schlüsselwort assert prüft, ob die Bedingung ergebnis == 4 wahr ist. Wenn ja, läuft der Test weiter. Wenn nein, bricht der Test mit einem Fehler ab.

Was bedeutet das konkret? Wenn addiere(2, 2) den Wert 4 zurückgibt, ist der Test erfolgreich. Gibt die Funktion etwas anderes zurück (z.B. 5), schlägt die Assertion fehl und wir wissen: Hier ist ein Bug.

Was ist ein Bug?

Ein Bug (Fehler) ist ein Problem in der Software, das dazu führt, dass sie nicht wie erwartet funktioniert. Bugs können von harmlosen Darstellungsfehlern bis zu kritischen Sicherheitslücken reichen.

Arten von Bugs:

  • Syntaxfehler: Code, der nicht kompiliert oder interpretiert werden kann
  • Logikfehler: Code läuft, aber liefert falsche Ergebnisse
  • Laufzeitfehler: Code stürzt während der Ausführung ab
  • Sicherheitslücken: Fehler, die Angreifern Zugang ermöglichen

Der Begriff “Bug” geht auf Grace Hopper zurück, die 1947 eine echte Motte in einem Computer fand, die einen Fehler verursachte.

Warum ist das wichtig? Die Schwere eines Bugs hängt vom Kontext ab. Ein Tippfehler auf einer Website ist ärgerlich. Ein Logikfehler in einer Bankensoftware kann Millionen kosten.

Was ist eine Test Suite?

Eine Test Suite ist eine Sammlung zusammengehöriger Testfälle. Statt Tests einzeln zu verwalten, gruppierst du sie logisch.

Typische Gruppierungen:

  • Nach Funktion: “Alle Tests für die Login-Funktion”
  • Nach Modul: “Alle Tests für das Bezahlsystem”
  • Nach Priorität: “Kritische Tests”, “Smoke Tests”
  • Nach Ausführungszeit: “Schnelle Tests”, “Lange Integrationstests”

Vorteile von Test Suites:

  • Organisation: Übersichtliche Struktur bei vielen Tests
  • Selektive Ausführung: Nur bestimmte Test-Gruppen ausführen
  • Reporting: Ergebnisse pro Suite auswerten

Was bedeutet das konkret? Bei einem E-Commerce-System könntest du Test Suites haben für: Benutzerverwaltung, Produktkatalog, Warenkorb, Checkout, Bezahlung. So kannst du nach einer Änderung am Warenkorb gezielt nur die Warenkorb-Tests ausführen.

Was ist ein Regressionstest?

Ein Regressionstest prüft, ob bestehende Funktionen nach Änderungen noch korrekt arbeiten.

Das Problem ohne Regressionstests:

“Ich habe Feature A repariert, aber dabei Feature B kaputt gemacht.”

Dieses Problem tritt in komplexen Systemen häufig auf. Änderungen an einer Stelle können unerwartete Auswirkungen an anderen Stellen haben.

Wie funktionieren Regressionstests?

  1. Du hast eine Sammlung von Tests, die alle wichtigen Funktionen abdecken
  2. Nach jeder Code-Änderung führst du diese Tests aus
  3. Schlägt ein Test fehl, der vorher funktionierte, hast du eine Regression gefunden

Warum ist das wichtig? Regressionstests geben dir Sicherheit bei jeder Änderung. Du kannst Code refactoren, Features hinzufügen oder Bugs fixen und weißt sofort, wenn du etwas anderes kaputt gemacht hast.

In der Praxis: Regressionstests werden meist automatisiert und bei jedem Commit ausgeführt (Continuous Integration). So werden Probleme sofort erkannt.

Tests im Software Development Life Cycle

Der Software Development Life Cycle (SDLC) umfasst alle Phasen von der Planung bis zur Wartung. Tests sind kein isolierter Schritt am Ende, sondern begleiten den gesamten Prozess.

Frühe Integration von Tests:

  • Planungsphase: Teststrategien definieren, Testumfang festlegen. Was muss getestet werden?
  • Analyse & Design: Testfälle aus Anforderungen ableiten. Wie soll sich die Software verhalten?
  • Entwicklungsphase: Unit-Tests für einzelne Komponenten schreiben und ausführen.
  • Testphase: Systemtests, Integrationstests, Akzeptanztests durchführen.
  • Wartung: Regressionstests nach jeder Änderung.

Je früher ein Fehler gefunden wird, desto günstiger ist seine Behebung. Ein Bug in der Entwicklungsphase zu finden kostet einen Bruchteil dessen, was er in der Produktion kosten würde.

Moderne Ansätze wie Agile und DevOps integrieren Tests noch enger in den Entwicklungsalltag. In späteren Lektionen lernst du Continuous Integration und Continuous Testing kennen.

Praxis: Das AAA-Pattern für strukturierte Tests

Ein bewährtes Muster für gut strukturierte Tests ist das AAA-Pattern: Arrange, Act, Assert.

Schauen wir uns ein vollständiges Beispiel an:

def berechne_rabatt(preis, prozent):
    """Berechnet den rabattierten Preis."""
    if prozent < 0 or prozent > 100:
        raise ValueError("Prozent muss zwischen 0 und 100 liegen")
    return preis * (1 - prozent / 100)
 
def test_rabatt_20_prozent():
    # Arrange: Testdaten vorbereiten
    preis = 100.0
    rabatt_prozent = 20
 
    # Act: Funktion ausführen
    ergebnis = berechne_rabatt(preis, rabatt_prozent)
 
    # Assert: Ergebnis prüfen
    assert ergebnis == 80.0

Erklärung des Codes

Die Funktion berechne_rabatt(preis, prozent):

Dies ist unsere zu testende Funktion. Sie prüft zuerst, ob der Prozentwert gültig ist (0-100), und berechnet dann den rabattierten Preis.

Das AAA-Pattern in test_rabatt_20_prozent():

# Arrange: Testdaten vorbereiten
preis = 100.0
rabatt_prozent = 20

Wie funktioniert das? Im Arrange-Schritt bereiten wir alles vor, was der Test braucht: Eingabedaten, Objekte, Konfigurationen. Hier definieren wir einen Preis von 100 Euro und einen Rabatt von 20%.

# Act: Funktion ausführen
ergebnis = berechne_rabatt(preis, rabatt_prozent)

Wie funktioniert das? Im Act-Schritt führen wir die zu testende Aktion aus. Hier rufen wir die Funktion mit unseren Testdaten auf.

# Assert: Ergebnis prüfen
assert ergebnis == 80.0

Wie funktioniert das? Im Assert-Schritt prüfen wir, ob das Ergebnis unseren Erwartungen entspricht. 100 Euro minus 20% Rabatt sollten 80 Euro ergeben.

Warum ist das wichtig? Das AAA-Pattern macht Tests lesbar und wartbar. Jeder, der den Test liest, versteht sofort: Was wird vorbereitet? Was wird ausgeführt? Was wird geprüft?

⏳ Lädt Dataview-Inhalt...

Kosten von Software-Tests

Software-Tests verursachen Kosten, die im Projektbudget eingeplant werden müssen.


Personalkosten

  • Qualifizierte Tester und Testmanager
  • Entwickler für Testautomatisierung
  • Schulungen und Weiterbildung

Werkzeuge und Technologien

  • Testmanagement-Software: TestRail, Jira, Azure DevOps
  • Automatisierungsframeworks: pytest, JUnit, Selenium, Cypress
  • Lizenzkosten: Kommerzielle Tools können teuer sein

Infrastruktur

  • Testumgebungen (Server, Datenbanken, Staging-Systeme)
  • Testdaten-Management
  • CI/CD-Pipelines (Jenkins, GitHub Actions, GitLab CI)

Zeitaufwand

  • Planung und Design von Testfällen
  • Durchführung und Analyse der Ergebnisse
  • Wartung von automatisierten Tests

Die Frage ist nicht, ob man testet, sondern wie viel und in welcher Form. Jedes Projekt hat andere Anforderungen und Budgets.

Nutzen von Software-Tests und die Rule of 10

Der Nutzen von Tests überwiegt die Kosten in den meisten Fällen deutlich:

Frühe Fehlererkennung:

Fehler in frühen Phasen zu finden spart erhebliche Kosten. Die Rule of 10 (auch 1:10:100-Regel) besagt:

  • Ein Fehler in der Entwicklungsphase zu beheben kostet 1x
  • Derselbe Fehler in der Testphase zu beheben kostet 10x
  • In der Produktion kostet die Behebung 100x oder mehr

Der Ariane-5-Absturz hätte mit einem einzigen Wertebereichs-Test verhindert werden können. Kosten des Tests: wenige Stunden Entwicklerzeit. Kosten des Fehlers: 370 Millionen Dollar.

Weitere Vorteile:

  • Qualitätssicherung: Systematische Tests garantieren stabile Software
  • Risikominimierung: Kritische Fehler werden vor dem Release entdeckt
  • Vertrauen: Entwickler können Änderungen sicher durchführen
  • Dokumentation: Tests dokumentieren das erwartete Verhalten
  • Refactoring-Sicherheit: Bei Umstrukturierungen zeigen Tests sofort, wenn etwas kaputt geht

Kosten-Nutzen-Abwägung in der Praxis

Die optimale Teststrategie hängt von mehreren Faktoren ab:

Risiko-basierte Priorisierung:

  • Sicherheitskritische Software (Medizin, Luftfahrt, Finanzwesen): Intensive Tests sind Pflicht. Hier kann ein Fehler Leben kosten oder Millionenschäden verursachen.
  • Business-kritische Funktionen: Kernfunktionen, die Umsatz generieren, brauchen mehr Tests als Randfunktionen.
  • Neue vs. bewährte Komponenten: Neuer Code birgt mehr Risiko als etablierter Code.

Praktische Faustregeln:

  • Teste die kritischsten Pfade zuerst (Happy Path + wichtigste Fehlerfälle)
  • Automatisiere wiederholte Tests (Regressionstests, CI/CD)
  • Investiere in Tests proportional zum Risiko eines Fehlers
  • Manuelle Tests für explorative Szenarien und Usability

Die 100%-Testabdeckung ist in der Praxis weder erreichbar noch sinnvoll. Ziel ist es, das beste Verhältnis von Aufwand zu Risikoreduktion zu finden.

Budgetbeschränkungen und Zeitrahmen beeinflussen immer, wie umfassend getestet werden kann. Die Kunst liegt darin, mit begrenzten Ressourcen das Maximum an Sicherheit zu erreichen.

⏳ Lädt Dataview-Inhalt...

Zusammenfassung und Ausblick

Zusammenfassung

In dieser Lerneinheit hast du die Grundlagen des Software-Testens kennengelernt:

Grundbegriffe:

  • Ein Testfall beschreibt eine konkrete Prüfsituation mit Eingaben, Bedingungen und erwarteten Ergebnissen.
  • Eine Assertion ist die Prüfung, ob das tatsächliche Ergebnis dem erwarteten entspricht.
  • Ein Bug ist ein Fehler in der Software, der zu unerwartetem Verhalten führt.
  • Eine Test Suite ist eine Sammlung zusammengehöriger Testfälle.
  • Regressionstests prüfen, ob bestehende Funktionen nach Änderungen noch funktionieren.

Tests im SDLC:

  • Tests begleiten den gesamten Entwicklungsprozess, nicht nur das Ende.
  • Frühe Fehlererkennung spart erhebliche Kosten (Rule of 10).

Kosten und Nutzen:

  • Tests verursachen Kosten (Personal, Tools, Zeit), aber der Nutzen überwiegt.
  • Die optimale Teststrategie hängt vom Risiko und den verfügbaren Ressourcen ab.

Praxis:

  • Das AAA-Pattern (Arrange, Act, Assert) strukturiert Tests klar und lesbar.

Ausblick

In der nächsten Lerneinheit beschäftigst du dich mit Teststufen und Testarten. Du lernst den Unterschied zwischen Unit-Tests, Integrationstests, Systemtests und Akzeptanztests kennen und verstehst, wann du welche Teststufe einsetzt.