Einführung in Unit-Tests

Unit-Tests sind eine Methode der Softwareentwicklung, bei der einzelne Teile (Units) eines Programms - typischerweise Funktionen oder Methoden - isoliert getestet werden. Der Zweck dieser Tests ist es, sicherzustellen, dass jeder Teil des Programms wie erwartet funktioniert. Unit-Tests helfen dabei, Fehler frühzeitig im Entwicklungsprozess zu erkennen und zu beheben, was die Qualität der Software verbessert, und die langfristige Wartung erleichtert.

Was sind Unit-Tests

Was muss getestet werden?

  • Kritische Aspekte:
    • Alle Kernfunktionalitäten und Geschäftslogik
    • Häufig verwendete oder fehleranfällige Bereiche
    • Randfälle und Ausnahmesituationen
    • Integrationsschnittstellen zu anderen Komponenten

Welche Testfälle?

  • Entwicklung von Testfällen:
    • Positivszenarien: Normaler Betrieb, bei dem erwartete Ergebnisse zurückgegeben werden
    • Negativszenarien: Fehlersituationen, ungültige Eingaben, um die Robustheit zu prüfen
    • Grenzwertanalysen: Testen an den Grenzen der Eingabebereiche
    • Rückwärtskompatibilität: Sicherstellen, dass Änderungen bestehende Funktionen nicht beeinträchtigen

Wann muss getestet werden?

  • Timing von Tests:
    • Entwicklungsphase: Unit-Tests sollten parallel zur Entwicklung geschrieben und ausgeführt werden
    • Nach Änderungen: Immer nach Anpassungen oder Erweiterungen des Codes
    • Continuous Integration (CI): Automatisierte Tests bei jedem Push in das Repository
    • Vor dem Deployment: Abschließende Tests vor dem Livegang

Erweiterte Themen in Unit-Tests

Testabdeckung (Code Coverage)

  • Bedeutung der Testabdeckung:
    • Messung des durch Tests abgedeckten Codeanteils
    • Ziel ist eine hohe Abdeckung für umfassende Testsicherheit

Test-Driven Development (TDD)

  • Was ist TDD?
    • Entwicklungsansatz, bei dem Tests vor dem Code geschrieben werden
    • Fördert designorientiertes Denken und sauberen Code

Mocking und Stubbing

  • Isolation von Tests:
    • Techniken zum Nachahmen von Abhängigkeiten in Tests
    • Wichtig für das Testen von externen Diensten oder komplexen Systemen

Regressionstests

  • Vermeidung von Regressionen:
    • Sicherstellung, dass Änderungen im Code keine vorhandenen Funktionen beeinträchtigen
    • Wiederholte Tests zum Schutz vor neuen Fehlern in altem Code

Testpflege und -aktualisierung

  • Wartung von Tests:
    • Regelmäßige Aktualisierung der Tests entsprechend Code-Änderungen
    • Sicherstellung der Relevanz und Genauigkeit von Tests

Integration in den Entwicklungsprozess

  • Einbettung in Softwareentwicklung:
    • Integration von Unit-Tests in Build-Prozesse und Continuous Integration
    • Teil der Code-Reviews und Delivery Pipelines

Performance-Testing

  • Überprüfung der Leistungsfähigkeit:
    • Tests zur Messung der Performance und Effizienz des Codes
    • Wichtig für leistungsintensive Anwendungen

Grundlagen von JUnit

Was ist JUnit?

  • JUnit - Ein Überblick:
    • Ein beliebtes Framework für Unit-Tests in der Java-Programmierung
    • Ermöglicht das Schreiben und Ausführen von wiederholbaren Tests

Key Components of JUnit Tests

  • Wichtige Bestandteile:
    • Testfälle (Test Cases): Einzelne Testeinheiten, die spezifische Teile des Codes testen
    • Test-Suites: Sammlungen von Testfällen
    • Assertions: Aussagen, die überprüfen, ob der Test die erwarteten Ergebnisse liefert
    • Test-Runner: Werkzeug zum Ausführen der Tests

Erstellen eines JUnit-Tests

  • Schritte zum Schreiben eines Tests:
    1. Importieren der JUnit-Bibliotheken
    2. Erstellen einer Testklasse
    3. Definieren von Testmethoden mit @Test Annotation
    4. Verwenden von Assertions zur Überprüfung der Ergebnisse

Beispiel eines einfachen JUnit-Tests

Erstellung einer einfachen Java-Klasse

  • Beispielklasse: Calculator
    • Eine einfache Klasse, die grundlegende mathematische Operationen ausführt
    • Methoden: add(int a, int b) und subtract(int a, int b)
public class Calculator {
    public int add(int a, int b) {
        return a + b;
    }

    public int subtract(int a, int b) {
        return a - b;
    }
}

Schreiben eines JUnit-Tests für die Klasse

  • JUnit-Testklasse: CalculatorTest
    • Testmethoden für jede Funktion der Calculator-Klasse
    • Verwendung von Assertions zur Überprüfung der Ergebnisse
import static org.junit.Assert.*;
import org.junit.Test;

public class CalculatorTest {

    @Test
    public void testAdd() {
        Calculator calculator = new Calculator();
        assertEquals(5, calculator.add(2, 3));
    }

    @Test
    public void testSubtract() {
        Calculator calculator = new Calculator();
        assertEquals(1, calculator.subtract(4, 3));
    }
}

Ausführen und Interpretieren von Testergebnissen

Wie man JUnit-Tests ausführt

  • Ausführungsmethoden:

    • Über eine integrierte Entwicklungsumgebung (IDE) wie Eclipse, IntelliJ IDEA
    • Verwendung von Build-Tools wie Maven oder Gradle
    • Kommandozeile mit JUnit-Befehlen
  • Beispiel: Ausführen mit Maven

    • Fügen Sie JUnit als Abhängigkeit in pom.xml ein
    • Ausführen von Tests mit mvn test

Projektstruktur

unit-tests-intro/
├── src/
│   ├── main/
│   │   └── java/
│   │       └── (Ihre Hauptklassen hier)
│   └── test/
│       └── java/
│           └── (Ihre Testklassen hier)
└── pom.xml

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.example</groupId>
    <artifactId>unit-tests-intro</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>

Interpretation der Ergebnisse

  • Erfolgreiche Tests:

    • Alle Assertions sind wahr; das Programm verhält sich wie erwartet
    • Keine Fehlermeldungen
  • Fehlgeschlagene Tests:

    • Mindestens eine Assertion ist falsch
    • Ausgabe von Fehlermeldungen und -details

Umgang mit fehlgeschlagenen Tests

  • Schritte zur Fehlerbehebung:

    1. Überprüfen Sie die Fehlermeldungen und Testausgaben
    2. Identifizieren Sie den fehlerhaften Teil des Codes
    3. Korrigieren Sie den Code und führen Sie die Tests erneut aus
  • Best Practices:

    • Schreiben Sie klare und aussagekräftige Testfälle
    • Überprüfen und aktualisieren Sie regelmäßig Ihre Tests

08 Einführung in Unit-Tests

By Harald Haberstroh

08 Einführung in Unit-Tests

  • 141