Testing-Time-Travel Teil 1: Testing-Grundlagen als wissenschaftliche Methode


Von Dr. Cassian Holt, Senior Architect & Programming Language Historian bei Java Fleet Systems Consulting in Essen-Rüttenscheid


🎯 Kurze Zusammenfassung – Das Wichtigste in 30 Sekunden

Dr. Cassian stellt sich vor und startet eine 3-Wochen-Testing-Reise mit Nova’s TaskApp! Testing ist angewandte Wissenschaft – jeder Test ist ein wissenschaftliches Experiment, das eine Hypothese über Code-Verhalten überprüft.

Key Learnings:

Testing = Wissenschaft – Hypothese → Experiment → Beobachtung → Schlussfolgerung
AAA-Pattern (Arrange-Act-Assert) ist die wissenschaftliche Methode für Tests
AssertJ macht Assertions lesbar wie natürliche Sprache
TaskValidator als erstes praktisches Testing-Beispiel

Sofort anwendbar: Erste Tests für Nova’s TaskApp mit JUnit 5 und AssertJ schreiben!

3-Wochen-Bootcamp: Jeden Dienstag & Donnerstag eine neue Testing-Superkraft! 🧪

🌟 Hallo Java Fleet Community – Dr. Cassian hier!

Grüße, Code-Entdecker! 👋

Ich bin Dr. Cassian Holt, und das ist mein erster Beitrag hier im Java Fleet Blog! Als Senior Architect und Programming Language Historian bringe ich eine etwas andere Perspektive mit: Ich sehe Code-Entwicklung als angewandte Wissenschaft.

Mein Background: Mit 47 Jahren und 25 Jahren Programming habe ich die komplette Java-Evolution miterlebt – angefangen 1999 mit Java 1.2, als ich frisch von der Uni kam und dachte, ich wüsste schon alles! 😅 Ich war dabei, als JUnit das erste Mal die Entwicklerwelt revolutionierte, habe die Geburt von Spring miterlebt und Lambda-Expressions bei Oracle diskutiert, bevor sie in Java 8 kamen.

Warum bin ich hier? Nach Nova’s ernüchterndem Learning Monday 2 gestern – wo Code Sentinel ihr gezeigt hat, wie wenig sie über Security wusste – kam Franz-Martin zu mir: „Cassian, Nova ist demotiviert. Du musst ihr zeigen, wie Testing Spaß macht und gleichzeitig ihre Confidence als Entwicklerin aufbaut!“

Genau das werden wir tun! Statt Code Sentinel’s „Hier ist alles was du falsch machst“-Ansatz zeige ich dir: Testing ist die eleganteste Art, brilliant zu programmieren! 🔬

Und genau das werden wir tun! 🔬

🎯 Warum diese Serie entstanden ist – Nova’s nächster Schritt!

Gestern las ich Nova’s Learning Monday 2, und ich war beeindruckt! Code Sentinel hatte ihr mit seinem Practice Friday gezeigt, wie Spring Security funktioniert, und Nova hat das brilliant gemeistert – von Panik zu funktionierender Authentication in einer Woche!

Aber am Ende ihres Posts schrieb sie etwas, das mich aufhorchen ließ:

„Dr. Cassian hat mir übrigens erzählt, dass Java diese Features von anderen Sprachen ‚geklaut‘ hat – ich bin gespannt auf die Geschichte dahinter!“

Das bin ich! 🤩 Und hier ist meine Antwort, Nova:

Testing ist die nächste logische Stufe deiner Entwicklung! Du hast jetzt eine funktionierende, sichere API. Aber woher weißt du, dass sie immer funktioniert? Woher weißt du, dass deine Security-Konfiguration wirklich schützt?

Die Antwort: Wissenschaftliche Tests! Mit Tests beweist du systematisch, dass dein Code korrekt ist. Das ist der Unterschied zwischen „es läuft auf meinem Rechner“ und „es läuft überall, immer, zuverlässig.“

Das werden wir in den nächsten 3 Wochen zusammen schaffen – jeden Dienstag und Donnerstag eine neue Testing-Superkraft für deine TaskApp! 🧪

🔬 Testing = Wissenschaft: Der Beweis

Lass mich dir zeigen, warum Testing und wissenschaftliche Methode identisch sind:

Wissenschaftliches Experiment:

  1. Hypothese aufstellen: „Wenn ich Wasser auf 100°C erhitze, dann verdampft es“
  2. Experiment entwerfen: Wasser erhitzen und Temperatur messen
  3. Durchführung: Experiment ausführen
  4. Beobachtung: Was passiert wirklich?
  5. Schlussfolgerung: Hypothese bestätigt oder widerlegt
  6. Reproduzierbarkeit: Andere können das Experiment wiederholen

Software-Test:

  1. Hypothese aufstellen: „Wenn ich einen Task mit leerem Titel erstelle, dann sollte eine Validierungsfehlermeldung kommen“
  2. Test entwerfen: Code schreiben, der diese Hypothese prüft
  3. Durchführung: Test ausführen
  4. Beobachtung: Wird der Test grün oder rot?
  5. Schlussfolgerung: Code-Verhalten bestätigt oder Bug gefunden
  6. Reproduzierbarkeit: Jeder Entwickler kann den Test ausführen

Siehst du es? 🤩 Tests sind wissenschaftliche Experimente für Code!

📱 Nova’s TaskApp als unser Test-Labor

Perfekt für unsere Testing-Reise: Nova hat bereits eine wunderbar funktionierende TaskApp gebaut! Lass uns sie als Grundlage für unsere ersten Testing-Experimente verwenden.

Nova’s Task-Entity (recap):

@Entity
public class Task {
    @Id @GeneratedValue
    private Long id;
    
    @Column(nullable = false)
    private String title;
    
    private String description;
    
    @Column(name = "is_completed")
    private boolean completed = false;
    
    @Enumerated(EnumType.STRING)
    private Priority priority = Priority.MEDIUM;
    
    @CreationTimestamp
    private LocalDateTime createdAt;
    
    // constructors, getters, setters...
    
    public Task() {}
    
    public Task(String title, String description) {
        this.title = title;
        this.description = description;
    }
}

public enum Priority {
    LOW, MEDIUM, HIGH, URGENT
}

Nova’s Controller (recap):

@RestController
@RequiredArgsConstructor
public class TaskController {
    
    private final TaskRepository taskRepository;
    
    @GetMapping("/api/tasks")
    public List<Task> getAllTasks() {
        return taskRepository.findAll();
    }
    
    @PostMapping("/api/tasks")
    public Task createTask(@RequestBody CreateTaskRequest request) {
        Task task = new Task(request.getTitle(), request.getDescription());
        if (request.getPriority() != null) {
            task.setPriority(request.getPriority());
        }
        return taskRepository.save(task);
    }
}

Perfekt! Das ist unser Labor. Jetzt machen wir es wissenschaftlich testbar! 🔬

🧪 Dein erstes wissenschaftliches Experiment: Task-Validation

Hypothese: Nova’s TaskApp sollte keine Tasks mit leerem Titel akzeptieren.

Problem: Momentan gibt es keine Validierung! Wir können Tasks mit leerem Titel erstellen. Das ist wahrscheinlich nicht gewollt.

Lösung: Erst den Test schreiben (unsere Hypothese formulieren), dann die Validierung implementieren.

Schritt 1: Maven Dependencies hinzufügen

<!-- Nova's pom.xml erweitern -->
<dependencies>
    <!-- Existing dependencies... -->
    
    <!-- JUnit 5 für Testing -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
    
    <!-- AssertJ für lesbare Assertions -->
    <dependency>
        <groupId>org.assertj</groupId>
        <artifactId>assertj-core</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

Was bekommen wir dadurch?

  • JUnit 5 (Jupiter): Das moderne Testing-Framework
  • AssertJ: Lesbare, fluent Assertions
  • Spring Boot Test: Integration mit Spring Context
  • Mockito: Für Mocking (brauchen wir später)

Schritt 2: Unsere erste TaskValidator-Klasse

// Erstelle: src/main/java/com/javafleet/taskmanager/service/TaskValidator.java
@Component
public class TaskValidator {
    
    public ValidationResult validate(Task task) {
        List<String> errors = new ArrayList<>();
        
        if (task.getTitle() == null || task.getTitle().trim().isEmpty()) {
            errors.add("Title cannot be empty");
        }
        
        if (task.getTitle() != null && task.getTitle().length() > 100) {
            errors.add("Title too long (max 100 characters)");
        }
        
        if (task.getDescription() != null && task.getDescription().length() > 500) {
            errors.add("Description too long (max 500 characters)");
        }
        
        return new ValidationResult(errors.isEmpty(), errors);
    }
}

// Erstelle: src/main/java/com/javafleet/taskmanager/service/ValidationResult.java
public class ValidationResult {
    private final boolean valid;
    private final List<String> errors;
    
    public ValidationResult(boolean valid, List<String> errors) {
        this.valid = valid;
        this.errors = errors != null ? errors : new ArrayList<>();
    }
    
    public boolean isValid() {
        return valid;
    }
    
    public List<String> getErrors() {
        return errors;
    }
    
    public String getFirstError() {
        return errors.isEmpty() ? null : errors.get(0);
    }
}

Schritt 3: Unser erstes wissenschaftliches Experiment (Test)!

// Erstelle: src/test/java/com/javafleet/taskmanager/service/TaskValidatorTest.java
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.*;

class TaskValidatorTest {
    
    private final TaskValidator validator = new TaskValidator();
    
    @Test
    @DisplayName("Should accept valid task with title and description")
    void shouldAcceptValidTask() {
        // Arrange - Vorbereitung unseres Experiments
        Task task = new Task("Learn Spring Boot Testing", "Master JUnit 5 and AssertJ");
        
        // Act - Durchführung des Experiments
        ValidationResult result = validator.validate(task);
        
        // Assert - Überprüfung unserer Hypothese
        assertThat(result.isValid()).isTrue();
        assertThat(result.getErrors()).isEmpty();
    }
    
    @Test
    @DisplayName("Should reject task with empty title")
    void shouldRejectEmptyTitle() {
        // Arrange - Das ist unsere Haupthypothese!
        Task taskWithEmptyTitle = new Task("", "Some description");
        
        // Act - Was passiert wirklich?
        ValidationResult result = validator.validate(taskWithEmptyTitle);
        
        // Assert - Hypothese bestätigt oder widerlegt?
        assertThat(result.isValid()).isFalse();
        assertThat(result.getErrors())
            .hasSize(1)
            .contains("Title cannot be empty");
    }
    
    @Test
    @DisplayName("Should reject task with null title")  
    void shouldRejectNullTitle() {
        // Arrange - Edge case testing
        Task taskWithNullTitle = new Task(null, "Some description");
        
        // Act
        ValidationResult result = validator.validate(taskWithNullTitle);
        
        // Assert
        assertThat(result.isValid()).isFalse();
        assertThat(result.getFirstError()).isEqualTo("Title cannot be empty");
    }
    
    @Test
    @DisplayName("Should reject task with title longer than 100 characters")
    void shouldRejectTooLongTitle() {
        // Arrange - Boundary testing
        String tooLongTitle = "x".repeat(101); // 101 Zeichen
        Task task = new Task(tooLongTitle, "Description");
        
        // Act
        ValidationResult result = validator.validate(task);
        
        // Assert
        assertThat(result.isValid()).isFalse();
        assertThat(result.getErrors()).contains("Title too long (max 100 characters)");
    }
    
    @Test  
    @DisplayName("Should accept task with exactly 100 character title")
    void shouldAcceptMaxLengthTitle() {
        // Arrange - Boundary testing (genau an der Grenze)
        String maxLengthTitle = "x".repeat(100); // Genau 100 Zeichen
        Task task = new Task(maxLengthTitle, "Description");
        
        // Act
        ValidationResult result = validator.validate(task);
        
        // Assert
        assertThat(result.isValid()).isTrue();
    }
}

🎯 Die AAA-Pattern: Arrange-Act-Assert

Schau dir die Struktur unserer Tests an: Jeder Test folgt dem AAA-Pattern – das ist die wissenschaftliche Methode für Tests!

Arrange (Vorbereitung):

Task task = new Task("Learn Spring Boot Testing", "Master JUnit 5 and AssertJ");

= Experimenteller Aufbau: Wir bereiten unsere „Versuchsanordnung“ vor – erstellen die Objekte, die wir testen wollen.

Act (Durchführung):

ValidationResult result = validator.validate(task);

= Experiment durchführen: Wir führen die Aktion aus, die wir testen wollen – rufen die Methode auf.

Assert (Überprüfung):

assertThat(result.isValid()).isTrue();
assertThat(result.getErrors()).isEmpty();

= Ergebnis bewerten: Wir überprüfen, ob das Ergebnis unseren Erwartungen entspricht.

Das ist pure wissenschaftliche Methode! 🔬

📚 AssertJ: Lesbare Assertions für Menschen

Nova, schau dir den Unterschied an:

Alte JUnit-Assertions (schwer lesbar):

// Schwer zu lesen und zu verstehen
assertTrue(result.isValid());
assertEquals(1, result.getErrors().size());
assertTrue(result.getErrors().contains("Title cannot be empty"));

AssertJ-Assertions (wie natürliche Sprache):

// Liest sich wie ein englischer Satz!
assertThat(result.isValid()).isTrue();
assertThat(result.getErrors())
    .hasSize(1)
    .contains("Title cannot be empty");

AssertJ-Magie: Du kannst Assertions verketten und sie lesen sich wie natürliche Sprache!

Weitere AssertJ-Beispiele für Nova’s TaskApp:

// String-Assertions
assertThat(task.getTitle())
    .isNotNull()
    .isNotEmpty()
    .hasSize(20)
    .startsWith("Learn")
    .contains("Spring")
    .endsWith("Testing");

// Collection-Assertions  
assertThat(result.getErrors())
    .isNotEmpty()
    .hasSize(2)
    .contains("Title cannot be empty", "Description too long")
    .doesNotContain("Invalid priority");

// Object-Assertions
assertThat(task)
    .isNotNull()
    .extracting(Task::getTitle, Task::getPriority)
    .containsExactly("Learn Testing", Priority.HIGH);

// Exception-Assertions
assertThatThrownBy(() -> taskService.createTask(null))
    .isInstanceOf(ValidationException.class)
    .hasMessage("Task cannot be null");

Ist das nicht elegant? Tests werden zu lesbarer Dokumentation deines Codes! 📖

🏃‍♂️ Deine ersten Tests ausführen

Mit Maven:

# Alle Tests ausführen
mvn test

# Nur TaskValidatorTest ausführen  
mvn test -Dtest=TaskValidatorTest

# Mit detailliertem Output
mvn test -Dtest=TaskValidatorTest -DforkCount=0

In deiner IDE:

  • IntelliJ IDEA: Rechtsklick auf Test-Klasse → „Run ‚TaskValidatorTest’“
  • Eclipse: Rechtsklick → „Run As“ → „JUnit Test“
  • VS Code: Test-Explorer oder Codelens „Run Test“

Erwartetes Ergebnis: Alle Tests sollten GRÜN sein! 🟢

Test-Output verstehen:

[INFO] -------------------------------------------------------
[INFO]  T E S T S
[INFO] -------------------------------------------------------
[INFO] Running com.javafleet.taskmanager.service.TaskValidatorTest
[INFO] Tests run: 5, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.123 s
[INFO] 
[INFO] Results:
[INFO] Tests run: 5, Failures: 0, Errors: 0, Skipped: 0
[INFO] BUILD SUCCESS

Was bedeutet das?

  • Tests run: 5 – Anzahl ausgeführter Tests
  • Failures: 0 – Tests die fehlschlugen (Assertion war falsch)
  • Errors: 0 – Tests die mit Exception abbrachen
  • Skipped: 0 – Tests die übersprungen wurden (@Disabled)

🎯 Test-Namen als lebende Dokumentation

Schau dir unsere Test-Namen an:

  • shouldAcceptValidTask()
  • shouldRejectEmptyTitle()
  • shouldRejectNullTitle()
  • shouldRejectTooLongTitle()
  • shouldAcceptMaxLengthTitle()

Jeder Name erzählt eine Geschichte! Wenn ein Test fehlschlägt, weißt du sofort:

  • Welches Verhalten getestet wird
  • Was schiefgegangen ist
  • Wo du suchen musst

Test-Namen-Pattern für Nova:

// Pattern: should[ExpectedBehavior]When[Condition]
@Test
@DisplayName("Should return high priority tasks first when sorting by priority")
void shouldReturnHighPriorityTasksFirstWhenSortingByPriority() {
    // Test implementation...
}

// Pattern: should[Action][Condition]  
@Test
@DisplayName("Should throw ValidationException when task title is null")
void shouldThrowValidationExceptionWhenTaskTitleIsNull() {
    // Test implementation...
}

Pro-Tip: Verwende @DisplayName() für noch lesbarere Namen in Test-Reports!

🧠 Warum Testing dein Gehirn trainiert

Nova, hier ist das Faszinierende: Testing macht dich zu einem besseren Entwickler, auch wenn du gar keine Tests schreibst!

1. Hypothetisches Denken:

Wenn du Tests schreibst, denkst du: „Was könnte schiefgehen? Welche Edge Cases gibt es?“

2. Klare Spezifikationen:

Tests zwingen dich, genau zu definieren, was dein Code machen soll.

3. Modulares Design:

Code, der testbar ist, ist automatisch besser strukturiert.

4. Debugging-Skills:

Du lernst, systematisch Probleme zu finden und zu lösen.

Das ist wie Krafttraining für dein Entwickler-Gehirn! 💪

🎯 Deine Challenge für diese Woche

Zeit für deine ersten wissenschaftlichen Experimente! 🧪

Aufgabe 1: Teste Nova’s Calculator (Aufwärm-Übung)

Erstelle diese Calculator-Klasse und schreibe Tests dafür:

// src/main/java/com/javafleet/taskmanager/service/Calculator.java
@Component
public class Calculator {
    
    public int add(int a, int b) {
        return a + b;
    }
    
    public int subtract(int a, int b) {
        return a - b;
    }
    
    public double divide(int a, int b) {
        if (b == 0) {
            throw new IllegalArgumentException("Division by zero is not allowed");
        }
        return (double) a / b;
    }
    
    public int multiply(int a, int b) {
        return a * b;
    }
}

Deine Test-Mission:

  • Teste Addition mit positiven/negativen Zahlen
  • Teste Subtraktion mit verschiedenen Kombinationen
  • Teste Division-by-Zero Exception mit assertThatThrownBy()
  • Teste Multiplikation mit 0 und negativen Zahlen

Erwartetes Ergebnis: Eine CalculatorTest-Klasse mit mindestens 6 Tests.

Aufgabe 2: Erweitere Nova’s TaskApp um Validation-Tests

Deine Mission: Erweitere TaskValidatorTest um diese zusätzlichen Szenarien:

@Test
@DisplayName("Should reject task with only whitespace title")
void shouldRejectWhitespaceOnlyTitle() {
    // Teste: "   " (nur Leerzeichen) sollte ungültig sein
}

@Test
@DisplayName("Should reject task with description longer than 500 characters")
void shouldRejectTooLongDescription() {
    // Teste: Beschreibung mit 501 Zeichen sollte ungültig sein
}

@Test
@DisplayName("Should accept task with null description")  
void shouldAcceptNullDescription() {
    // Teste: Beschreibung kann null sein (ist optional)
}

@Test
@DisplayName("Should accept task with empty description")
void shouldAcceptEmptyDescription() {
    // Teste: Leere Beschreibung ist okay
}

@Test
@DisplayName("Should collect multiple validation errors")
void shouldCollectMultipleValidationErrors() {
    // Teste: Task mit leerem Titel UND zu langer Beschreibung
    // sollte BEIDE Fehlermeldungen sammeln
}

Bonus-Challenge: Schreibe einen Test für dieses Szenario:

@Test
@DisplayName("Should trim whitespace from title before validation")
void shouldTrimWhitespaceFromTitle() {
    // Teste: "  Valid Title  " sollte als "Valid Title" validiert werden
}

Aufgabe 3: Experimentiere mit AssertJ

Schreibe einen Test, der alle diese AssertJ-Features verwendet:

@Test
@DisplayName("AssertJ exploration - testing task with all features")
void shouldDemonstrateAssertJFeatures() {
    // Erstelle eine Task mit verschiedenen Properties
    Task task = new Task("Learn AssertJ Magic", "Master fluent assertions");
    task.setPriority(Priority.HIGH);
    
    // Verwende ALLE diese AssertJ-Assertions:
    assertThat(task.getTitle())
        .isNotNull()
        .isNotEmpty()  
        .startsWith("Learn")
        .contains("AssertJ")
        .hasSize(18);
    
    assertThat(task.getPriority())
        .isNotNull()
        .isEqualTo(Priority.HIGH);
        
    assertThat(task)
        .extracting(Task::getTitle, Task::getDescription, Task::getPriority)
        .containsExactly("Learn AssertJ Magic", "Master fluent assertions", Priority.HIGH);
}

📅 Was kommt diese und nächste Woche?

Unser 3-Wochen-Testing-Bootcamp (jeden Dienstag & Donnerstag):

Diese Woche:

  • Heute (Dienstag): Testing-Grundlagen & deine ersten Experimente
  • Donnerstag: Die Test-Pyramide als Physik + Integration Tests

Nächste Woche:

  • Dienstag: TDD in der Praxis + Property-Based Testing
  • Donnerstag: Legacy-Code testen + Charakterisierungstests

Finale Woche:

  • Dienstag: Advanced Testing-Patterns + Mutation Testing
  • Donnerstag: Chaos Engineering + deine Testing-Strategie

Nach 3 Wochen hast du: Solide Testing-Foundation, Confidence in deinem Code, und Werkzeuge für jede Situation! 🎯

💡 Abschluss: Dein Testing-Mindset

Nova, nach dieser ersten Testing-Session solltest du verstehen:

Tests sind wissenschaftliche Experimente – sie beweisen, dass dein Code funktioniert
AAA-Pattern (Arrange-Act-Assert) ist die Struktur für gute Tests
AssertJ macht Assertions lesbar wie natürliche Sprache
Test-Namen sind lebende Dokumentation deines Codes
Testing trainiert dein Entwickler-Gehirn systematisch zu denken

Das wichtigste: Testing ist nicht extra Arbeit – es ist investment in code quality!

Jeder Test, den du heute schreibst, spart dir morgen Stunden beim Debugging. Jeder Test ist ein kleiner wissenschaftlicher Beweis, dass dein Code tut, was er soll.

Und Nova: Nach Code Sentinel’s Kritik gestern bist du vielleicht verunsichert. Das ist normal! Aber jetzt hast du die Werkzeuge, um systematic quality in deinen Code zu bringen. Mit Tests beweist du, dass dein Code gut ist – wissenschaftlich!

Wie ein Wissenschaftler sagen würde: „Vertrauen ist gut, testen ist besser!“ 🔬



📅 Ausblick: Was kommt als nächstes?

Donnerstag (Teil 2): Die Test-Pyramide als Physik – warum Unit Tests wie Quantenmechanik funktionieren und wie du Integration-Tests für Nova’s TaskApp schreibst. Plus: Deine Challenge-Lösungen werden besprochen!

Sneak Preview: Wir werden Nova’s TaskService mit echten Spring Boot Integration-Tests testen und dabei Mocking mit @MockBean kennenlernen. Spoiler: Es ist wie ein wissenschaftliches Labor mit kontrollierten Bedingungen! 🔬


💬 Community-Diskussion

Wie waren eure ersten Testing-Erfahrungen? Hattet ihr auch den „Tests sind nur extra Arbeit“-Moment? Oder andere Testing-Überraschungen?

Schreibt in die Kommentare:

  • Testing: Liebe auf den ersten Blick oder Hassliebe?
  • AssertJ vs. klassische Assertions: Was findet ihr lesbarer?
  • Nova’s TaskApp: Welche anderen Validierungs-Szenarien fallen euch ein?

Erfahrene Entwickler: Wie erklärt ihr Newbies den Unterschied zwischen Testing und Debugging? Habt ihr gute Analogien?

Andere Juniors: Falls ihr ähnliche Verwirrung mit Testing hattet – ihr seid nicht allein! Teilt eure Fragen!


FAQ – Häufige Fragen zum Testing-Einstieg

F: Warum soll ich Tests schreiben wenn mein Code bereits funktioniert?
A: Weil „funktioniert jetzt“ nicht „funktioniert immer“ bedeutet! Tests sind wie Sicherheitsgurte – du brauchst sie nicht jeden Tag, aber wenn doch, sind sie lebensrettend. Außerdem: Woher weißt du, dass dein Code bei Edge Cases funktioniert, wenn du sie nie getestet hast?

F: Ist AssertJ wirklich notwendig oder reichen JUnit-Assertions?
A: AssertJ ist nicht notwendig, aber viel lesbarer. assertThat(result.getErrors()).hasSize(2).contains("Title empty") liest sich wie ein englischer Satz. Das macht Tests zur lebenden Dokumentation deines Codes!

F: Wie viel Zeit sollte ich für Tests einplanen?
A: Als Faustregel: 30-50% deiner Entwicklungszeit. Das klingt viel, aber du sparst diese Zeit beim Debugging wieder ein. Lieber 2 Stunden testen als 8 Stunden debuggen!

F: Soll ich Tests für einfache Getter/Setter schreiben?
A: Normalerweise nein – es sei denn, sie enthalten Business-Logic. Teste das Verhalten, nicht die Implementation. Ein einfaches getName() braucht keinen Test, aber getDisplayName() mit Formatierung schon!

F: Was ist wenn mein Test fehlschlägt – Bug im Code oder Bug im Test?
A: Beide möglich! Deshalb: Test zuerst genau lesen, dann Code überprüfen. Ein fehlschlagender Test ist Information, kein Problem. Er sagt dir: „Hier stimmt etwas nicht mit deinen Erwartungen!“

F: Kann ich Tests für Nova’s TaskApp auch ohne Spring Boot schreiben?
A: Ja! Unit Tests wie TaskValidatorTest brauchen kein Spring. Nur Integration-Tests brauchen @SpringBootTest. Das ist der Vorteil der Test-Pyramide – die meisten Tests sind schnelle, einfache Unit Tests!


Happy Testing, und bis Donnerstag!

Stay curious, stay scientific! ⚗️✨


Tags: #Testing #JUnit5 #AssertJ #TaskApp #ScientificMethod #JavaTesting #TestingGrundlagen #NovaLearns


📋 Quick Reference: JUnit 5 + AssertJ Cheatsheet

// JUnit 5 Basics
@Test                          // Standard Test
@DisplayName("Human readable") // Lesbarer Test-Name  
@ParameterizedTest            // Test mit mehreren Inputs
@Disabled("Reason")           // Test temporär deaktivieren

// AssertJ Assertions
assertThat(actual).isEqualTo(expected);
assertThat(text).isNotNull().isNotEmpty().contains("word");
assertThat(list).hasSize(3).contains("item1", "item2");
assertThat(number).isPositive().isGreaterThan(0).isLessThan(100);

// Exception Testing
assertThatThrownBy(() -> methodCall())
    .isInstanceOf(IllegalArgumentException.class)
    .hasMessage("Expected message");

Bookmark this – du wirst es brauchen! 🔖


🚀 GitHub Repository & Community

Den kompletten Code aus diesem Tutorial findest du hier: 📂 Java Fleet Testing Series – Teil 1

# Repository klonen und ausprobieren:
git clone https://github.com/java-fleet-systems/testing-series.git
cd testing-series
git checkout teil-1-grundlagen
mvn test

Im Repository findest du:

  • Komplette TaskApp mit TaskValidator und ValidationResult
  • Alle Test-Beispiele aus diesem Tutorial
  • Maven-Konfiguration mit JUnit 5 und AssertJ
  • README mit Schritt-für-Schritt-Anleitung
  • Challenge-Templates für deine Aufgaben

Deine Challenge-Lösungen: 📤 Erstelle einen PR mit deinen Challenge-Lösungen – wir reviewen sie in Teil 2!


Happy Testing, und bis Donnerstag!

Stay curious, stay scientific! ⚗️✨


Kommentare

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert