JaCoCo richtig nutzen – Test-Qualität statt Test-Quantität

Modul 1: Foundations & Basics | Teil 3 von 4

Von Code Sentinel, Technical Project Manager bei Java Fleet Systems Consulting
Für dich und die Java Fleet Community


📍 Deine Position in der Serie

ModulTeilThemaStatus
Foundations1Erste Pipeline✅ Fertig
Foundations2Security Gates✅ Fertig
Foundations→ 3Coverage Gates👉 DU BIST HIER
Foundations4Quality Gates🔒 Nächste Woche
Docker5-7Container & Registry🔒 Später
Deployment8-10Strategien & K8s🔒 Später
Enterprise11-12Advanced Patterns🔒 Später

Dauer heute: 15 Minuten Lesezeit
Dein Ziel: Verstehen was Coverage wirklich misst

Coverage Gates

📚 Was du bisher gelernt hast

In Teil 1 hast du gelernt:

  • ✅ Deine erste CI/CD Pipeline zu bauen
  • ✅ GitHub Actions und Jenkins zu nutzen
  • ✅ Automatische Builds und Tests

In Teil 2 hast du gelernt:

  • ✅ OWASP Dependency Check für Java-Dependencies
  • ✅ Trivy für Container-Security
  • ✅ Security-Reports zu lesen und CVEs zu fixen

Das Problem das übrig blieb: Deine Pipeline ist sicher – aber testen deine Tests wirklich was?

Heute lernen wir, Coverage richtig zu messen und zu interpretieren.


⚡ Was du in den nächsten 15 Minuten lernst

Nach diesem Beitrag kannst du:

  • ✅ Verstehen warum 95% Coverage Production trotzdem killen kann
  • ✅ JaCoCo in deine Pipeline integrieren
  • ✅ Line, Branch und Complexity Coverage unterscheiden
  • ✅ Sinnvolle von nutzlosen Tests unterscheiden
  • ✅ Coverage-Gates richtig konfigurieren

Dein größter Gewinn heute: Du merkst welche Tests wirklich schützen und welche nur Zahlen machen.


👋 Moin! Code Sentinel hier

Schön, dass du wieder dabei bist!

Erinnerst du dich? In Teil 2 haben wir Security Gates gebaut. Anna aus München hat sie implementiert und war begeistert. Bis Donnerstag. Da kam der Anruf vom Kunden:

„Anna, euer neues Feature hat Production komplett zerschossen. Aber die Pipeline war doch grün? 147 Tests passed, 95% Coverage! Was ist passiert?“

Anna um 18:30 Uhr:

😰 Production down
😰 Alle Tests grün
😰 95% Coverage
😰 Aber: Tests testen nichts Wichtiges
😰 Incident Report schreiben

Gestern kam Kofi zu mir mit seiner Test-Suite. 200 Tests, alle grün, 98% Coverage. „Das ist doch gut, oder?“

Ich schaute mir einen Test an:

@Test
void testCreateUser() {
    UserService service = new UserService();
    service.createUser("John", "john@example.com");
    // Kein Assert! Aber Line wurde ausgeführt = Coverage ✅
}

Das Problem: Line wurde ausgeführt, aber nichts verifiziert. 98% Coverage, 0% Nutzen.

Heute lernen wir den Unterschied zwischen Coverage-Zahlen und echtem Testing. Lass uns das zusammen durchgehen! 🎯


🎯 Das Problem: Coverage ≠ Quality

Was sind Coverage Gates überhaupt?

Coverage Gates in CI/CD sind automatische Prüfpunkte, die deinen Build stoppen, wenn Test-Coverage zu niedrig ist.

Stell dir vor:

Deine Pipeline:
├─ Build ✅
├─ Tests ✅ (147 passed)
├─ Security ✅ (keine CVEs)
└─ Coverage Gate ❌ FAILED
    "Branch Coverage 68% < Minimum 75%"
    
BUILD STOPPED ❌

Das ist ein Coverage Gate!

Es sagt: „Tests sind grün, ABER sie testen nicht genug verschiedene Fälle. Ich lasse dich nicht deployen, bis du fehlende Tests hinzufügst.“

Warum brauchst du Coverage Gates in der Pipeline?

Problem ohne Coverage Gate:

Entwickler schreibt Code → Tests laufen durch → Deploy
                                    ↑
                          Aber testen die Tests genug?
                          Niemand prüft das!

Mit Coverage Gate:

Entwickler schreibt Code → Tests laufen durch → Coverage-Check
                                                      ↓
                                           Coverage zu niedrig?
                                                 ↓         ↓
                                               Ja ❌      Nein ✅
                                                 ↓         ↓
                                         Build fails   Deploy

Der Vorteil: Die Maschine erzwingt Test-Qualität. Nicht optional, nicht „sollte man“, sondern MUSS.

Was ist JaCoCo?

JaCoCo = Java Code Coverage

Ein kostenloses, Open-Source-Tool, das misst welche Teile deines Codes von Tests ausgeführt werden.

Stell dir vor, JaCoCo ist wie ein Detektiv der zuschaut:

public int divide(int a, int b) {
    if (b == 0) {              // Zeile 1 - JaCoCo: "Wurde ausgeführt ✅"
        throw new Exception(); // Zeile 2 - JaCoCo: "Wurde NIE ausgeführt ❌"
    }
    return a / b;              // Zeile 3 - JaCoCo: "Wurde ausgeführt ✅"
}

@Test
void test() {
    divide(10, 2);  // Nur normaler Fall getestet
}

// JaCoCo-Report:
// Line Coverage: 66% (2 von 3 Zeilen ausgeführt)
// Branch Coverage: 50% (nur if-true getestet, if-false fehlt)

Was JaCoCo macht:

  1. Instrumentiert deinen Code beim Test (fügt unsichtbare Marker ein)
  2. Beobachtet welche Zeilen/Branches ausgeführt werden
  3. Erstellt Reports als HTML, XML oder CSV
  4. Prüft gegen Thresholds (z.B. „mindestens 80% Coverage“)
  5. Stoppt Build wenn Thresholds unterschritten werden

Warum JaCoCo in CI/CD?

Ohne JaCoCo:
└─ Du weißt nicht welche Code-Teile ungetestet sind

Mit JaCoCo:
├─ HTML-Report zeigt rot: "Diese Zeilen nie getestet!"
├─ Pipeline stoppt: "Coverage zu niedrig!"
└─ Du musst fehlende Tests hinzufügen

JaCoCo ist das Standard-Tool für Java-Coverage:

  • ✅ Kostenlos & Open Source
  • ✅ Maven & Gradle Integration
  • ✅ Funktioniert mit JUnit, TestNG, etc.
  • ✅ Detaillierte Reports (Zeile für Zeile)
  • ✅ Seit 2009 in Produktion (stabil!)

Alternativen zu JaCoCo:

  • Cobertura (älter, weniger aktiv)
  • IntelliJ Coverage (nur IDE, nicht Pipeline)
  • Emma (veraltet)

Für CI/CD = JaCoCo ist Standard!

Coverage Gates sind wie Security Gates:

Erinnerst du dich an Teil 2?

  • OWASP stoppt Build bei CVEs
  • Trivy stoppt Build bei Container-Vulnerabilities

Jetzt in Teil 3:

  • JaCoCo stoppt Build bei zu niedriger Coverage

Alle zusammen = Quality-Pipeline:

Code → Build → Tests → Coverage ✅ → Security ✅ → Deploy
                         ↓              ↓
                    Zu niedrig?    Vulnerabilities?
                         ↓              ↓
                    BUILD FAILS    BUILD FAILS

Was Anna’s 95% Coverage wirklich bedeuteten:

// Anna's User-Service
public class UserService {
    public User createUser(String name, String email) {
        if (name == null || email == null) {
            throw new IllegalArgumentException("Required!");
        }
        
        if (!email.contains("@")) {
            throw new IllegalArgumentException("Invalid email!");
        }
        
        User user = new User(name, email);
        database.save(user);
        return user;
    }
}

Anna’s Test mit 100% Line Coverage:

@Test
void testCreateUser() {
    UserService service = new UserService();
    User user = service.createUser("John", "john@example.com");
    
    // Das war's! Kein Assert!
    // Aber alle Lines wurden ausgeführt = 100% Coverage ✅
}

Was dieser Test NICHT testet:

  • ❌ Gibt die Methode den richtigen User zurück?
  • ❌ Was passiert bei name = null?
  • ❌ Was passiert bei email ohne @?
  • ❌ Wird der User in der Datenbank gespeichert?
  • ❌ Funktioniert überhaupt irgendwas?

Warum ist Coverage trotzdem 100%?

Coverage misst nur: „Wurde diese Zeile Code ausgeführt?“
Coverage misst NICHT: „Wurde diese Zeile Code richtig getestet?“


📊 Die 3 Arten von Coverage (JaCoCo)

1. Line Coverage – „Wurde diese Zeile ausgeführt?“

public int divide(int a, int b) {
    if (b == 0) {                    // Line 1
        throw new Exception();        // Line 2
    }
    return a / b;                     // Line 3
}

@Test
void testDivide() {
    divide(10, 2);  // Führt Line 1 und 3 aus
    // Line Coverage: 66% (2 von 3 Lines)
}

Das Problem:

  • Line 2 wurde nie ausgeführt
  • Exception-Handling nicht getestet
  • Aber: „66% Coverage sieht doch OK aus?“

2. Branch Coverage – „Wurden alle If/Else-Zweige getestet?“

public String checkAge(int age) {
    if (age >= 18) {              // Branch-Point!
        return "adult";            // Branch 1 (true)
    } else {
        return "minor";            // Branch 2 (false)
    }
}

// Schlechter Test
@Test
void testCheckAge() {
    checkAge(25);  // Nur Branch 1 getestet
    // Line Coverage: 100% ✅
    // Branch Coverage: 50% ❌
}

// Guter Test
@Test
void testCheckAge() {
    assertThat(checkAge(25)).isEqualTo("adult");   // Branch 1
    assertThat(checkAge(15)).isEqualTo("minor");   // Branch 2
    // Line Coverage: 100% ✅
    // Branch Coverage: 100% ✅
}

Branch Coverage ist wichtiger als Line Coverage!

Warum? Weil Bugs oft in if/else-Zweigen versteckt sind, die nie getestet wurden.

3. Complexity Coverage – „Wurden alle möglichen Pfade getestet?“

public String processUser(User user) {
    if (user == null) return "error";           // Pfad 1
    if (!user.isActive()) return "inactive";     // Pfad 2
    if (user.getAge() < 18) return "minor";      // Pfad 3
    if (user.hasRole("admin")) return "admin";   // Pfad 4
    if (user.hasRole("user")) return "user";     // Pfad 5
    return "guest";                              // Pfad 6
}

// Schlechter Test
@Test
void testProcessUser() {
    User user = new User("John", 25, true);
    processUser(user);  // Nur Pfad 6 getestet
    // Line Coverage: 100% ✅
    // Branch Coverage: ~16% ❌
    // Complexity Coverage: ~16% ❌
}

Complexity Coverage basiert auf Cyclomatic Complexity:

  • Je mehr If/Else/Switch/Loops, desto komplexer
  • Je komplexer, desto mehr verschiedene Pfade
  • Alle Pfade sollten getestet sein

Code Sentinel’s Tipp:

„Branch und Complexity Coverage sind mir wichtiger als Line Coverage. Bugs verstecken sich in nicht-getesteten Zweigen, nicht in nicht-ausgeführten Lines.“


💻 JaCoCo in GitHub Actions integrieren

Schritt 1: pom.xml konfigurieren

<project>
    <build>
        <plugins>
            <!-- JaCoCo Plugin -->
            <plugin>
                <groupId>org.jacoco</groupId>
                <artifactId>jacoco-maven-plugin</artifactId>
                <version>0.8.11</version>
                <executions>
                    <!-- Step 1: Prepare Agent -->
                    <!-- Agent instrumentiert deinen Code beim Test -->
                    <execution>
                        <id>prepare-agent</id>
                        <goals>
                            <goal>prepare-agent</goal>
                        </goals>
                    </execution>
                    
                    <!-- Step 2: Generate Report -->
                    <!-- Nach Tests: Report erstellen -->
                    <execution>
                        <id>report</id>
                        <phase>test</phase>
                        <goals>
                            <goal>report</goal>
                        </goals>
                    </execution>
                    
                    <!-- Step 3: Check Thresholds -->
                    <!-- Coverage-Gates prüfen -->
                    <execution>
                        <id>check</id>
                        <goals>
                            <goal>check</goal>
                        </goals>
                        <configuration>
                            <rules>
                                <rule>
                                    <element>BUNDLE</element>
                                    <limits>
                                        <!-- Line Coverage: Min 80% -->
                                        <limit>
                                            <counter>LINE</counter>
                                            <value>COVEREDRATIO</value>
                                            <minimum>0.80</minimum>
                                        </limit>
                                        
                                        <!-- Branch Coverage: Min 75% -->
                                        <limit>
                                            <counter>BRANCH</counter>
                                            <value>COVEREDRATIO</value>
                                            <minimum>0.75</minimum>
                                        </limit>
                                        
                                        <!-- Complexity Coverage: Min 70% -->
                                        <limit>
                                            <counter>COMPLEXITY</counter>
                                            <value>COVEREDRATIO</value>
                                            <minimum>0.70</minimum>
                                        </limit>
                                    </limits>
                                </rule>
                            </rules>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

Was bedeuten die Thresholds?

  • Line 80%: 80% der Zeilen müssen ausgeführt werden
  • Branch 75%: 75% der If/Else-Zweige müssen getestet sein
  • Complexity 70%: 70% der komplexen Pfade müssen abgedeckt sein

Warum diese Zahlen?

„80/75/70 ist Industry-Standard. Höher ist besser, aber 100% ist unrealistisch. Manche Lines (Getter/Setter, toString) muss man nicht testen.“

Schritt 2: GitHub Actions Pipeline

# .github/workflows/coverage-gate.yml
name: Coverage Gate

on:
  push:
    branches: [ main, develop ]
  pull_request:
    branches: [ main ]

jobs:
  test-with-coverage:
    runs-on: ubuntu-latest
    
    steps:
    # Code holen
    - name: Checkout code
      uses: actions/checkout@v4
    
    # Java installieren
    - name: Set up JDK 21
      uses: actions/setup-java@v4
      with:
        java-version: '21'
        distribution: 'temurin'
        cache: 'maven'
    
    # Tests mit Coverage ausführen
    - name: Run Tests with Coverage
      run: mvn clean test jacoco:report
    
    # Was macht das?
    # 1. clean = Alles aufräumen
    # 2. test = Alle Tests laufen lassen
    # 3. jacoco:report = Coverage-Report erstellen
    #    → Erstellt target/site/jacoco/index.html
    
    # Coverage-Thresholds prüfen
    - name: Check Coverage Thresholds
      run: mvn jacoco:check
    
    # Was macht das?
    # Prüft gegen die Limits in pom.xml
    # Bei Unterschreitung → Exit-Code 1 → Build fails!
    
    # Coverage-Report hochladen
    - name: Upload Coverage Report
      if: always()  # Auch bei Failure!
      uses: actions/upload-artifact@v3
      with:
        name: coverage-report
        path: target/site/jacoco/
    
    # Coverage-Badge generieren
    - name: Generate Coverage Badge
      uses: cicirello/jacoco-badge-generator@v2
      with:
        generate-branches-badge: true
        jacoco-csv-file: target/site/jacoco/jacoco.csv
    
    # Coverage als PR-Comment
    - name: Comment Coverage on PR
      if: github.event_name == 'pull_request'
      uses: madrapps/jacoco-report@v1.6
      with:
        paths: target/site/jacoco/jacoco.xml
        token: ${{ secrets.GITHUB_TOKEN }}
        min-coverage-overall: 80
        min-coverage-changed-files: 80

Was siehst du nach dem Push?

GitHub → Actions → Coverage Gate

Coverage Gate (1m 45s)
├─ Checkout ✅
├─ Setup JDK ✅
├─ Run Tests with Coverage ✅
│   └─ 147 tests passed
│       Coverage: Line 82%, Branch 68%, Complexity 71%
│
├─ Check Coverage Thresholds ❌ FAILED
│   
│   ERROR: Branch coverage 68% below minimum 75%
│   
│   Details:
│   - Line Coverage: 82% ✅ (min: 80%)
│   - Branch Coverage: 68% ❌ (min: 75%)
│   - Complexity Coverage: 71% ✅ (min: 70%)
│
└─ Upload Coverage Report ✅

BUILD FAILED ❌
Reason: Branch coverage below threshold

Was machst du jetzt?

  1. Download Coverage Report (Artifacts)
  2. Öffne index.html im Browser
  3. Rot markierte Bereiche anschauen
  4. Fehlende Branch-Tests hinzufügen

🏢 Jenkins: Coverage Gate

// Jenkinsfile - Coverage Stage
stage('Coverage Gate') {
    steps {
        // Tests mit Coverage
        sh 'mvn clean test jacoco:report'
        
        // Coverage-Report in Jenkins anzeigen
        jacoco(
            execPattern: '**/target/jacoco.exec',
            classPattern: '**/target/classes',
            sourcePattern: '**/src/main/java',
            changeBuildStatus: true,  // Build fails bei Unterschreitung
            minimumLineCoverage: '80',
            minimumBranchCoverage: '75',
            minimumComplexityCoverage: '70'
        )
    }
    
    post {
        always {
            // HTML-Report publishen
            publishHTML([
                reportDir: 'target/site/jacoco',
                reportFiles: 'index.html',
                reportName: 'JaCoCo Coverage Report'
            ])
        }
        
        failure {
            mail to: 'team@java-fleet.com',
                 subject: "Coverage Gate Failed: ${env.JOB_NAME}",
                 body: """
                 Build ${env.BUILD_NUMBER} unterschreitet Coverage-Thresholds.
                 
                 Report: ${env.BUILD_URL}JaCoCo_Coverage_Report
                 
                 Bitte fehlende Tests hinzufügen!
                 """
        }
    }
}

🎓 Gute vs. Schlechte Tests

Anna’s Lernkurve:

Vorher (schlechte Tests):

@Test
void testCreateUser() {
    UserService service = new UserService();
    service.createUser("John", "john@example.com");
    // Kein Assert! Coverage: 100% ✅, Nutzen: 0% ❌
}

@Test
void testDeleteUser() {
    UserService service = new UserService();
    service.deleteUser(1L);
    // Kein Assert! Coverage: 100% ✅, Nutzen: 0% ❌
}

Nachher (gute Tests):

@Test
void createUser_WithValidData_ReturnsUser() {
    // Arrange
    UserService service = new UserService();
    
    // Act
    User user = service.createUser("John", "john@example.com");
    
    // Assert
    assertThat(user).isNotNull();
    assertThat(user.getName()).isEqualTo("John");
    assertThat(user.getEmail()).isEqualTo("john@example.com");
    assertThat(user.getId()).isNotNull();
}

@Test
void createUser_WithNullName_ThrowsException() {
    UserService service = new UserService();
    
    assertThatThrownBy(() -> service.createUser(null, "john@example.com"))
        .isInstanceOf(IllegalArgumentException.class)
        .hasMessage("Required!");
}

@Test
void createUser_WithInvalidEmail_ThrowsException() {
    UserService service = new UserService();
    
    assertThatThrownBy(() -> service.createUser("John", "invalid"))
        .isInstanceOf(IllegalArgumentException.class)
        .hasMessage("Invalid email!");
}

Der Unterschied:

  • ✅ Jeder Test hat klare Asserts
  • ✅ Jeder Test testet einen spezifischen Fall
  • ✅ Happy Path UND Error Cases getestet
  • ✅ Alle Branches abgedeckt

✅ Checkpoint: Hast du Teil 3 gemeistert?

Kontrolliere:

  • [ ] JaCoCo in pom.xml konfiguriert
  • [ ] Coverage Gate in GitHub Actions/Jenkins
  • [ ] Verstehst den Unterschied Line/Branch/Complexity
  • [ ] Weißt warum 100% Coverage eine Lüge ist
  • [ ] Kannst gute von schlechten Tests unterscheiden
  • [ ] Hast mindestens einen Test mit Asserts geschrieben

Alles ✅? Du bist bereit für Teil 4 – Quality Gates!

Nicht alles geschafft?

  • Coverage-Reports brauchen Zeit zum Verstehen
  • Fang mit Line Coverage an, dann Branch
  • Nicht alle Tests müssen perfekt sein – Start small!

❓ FAQ – Coverage Edition

Frage 1: 95% Coverage – warum reicht das nicht?
Antwort: Coverage misst nur „wurde ausgeführt“, nicht „wurde richtig getestet“. 95% ohne Asserts = wertlos. Besser: 80% mit sinnvollen Tests!

Frage 2: Muss ich wirklich Getter/Setter testen?
Antwort: Nein! Triviale Code-Teile (Getter/Setter, toString, Constructors) kannst du von Coverage ausschließen. In pom.xml: <excludes>**/dto/**</excludes>

Frage 3: Branch Coverage ist zu niedrig – wie fixen?
Antwort: Schau dir den Report an. Rot = nicht getestet. Für jedes If/Else: Teste BEIDE Fälle. Wenn if (x > 0) → Teste x=5 UND x=-5!

Frage 4: 100% Coverage als Ziel?
Antwort: Unrealistisch! 80/75/70 ist Industry-Standard. Höher ist nice, aber kosten Entwicklungszeit. Lieber 80% gute Tests als 100% schlechte!

Frage 5: Wie viele Tests brauche ich?
Antwort: Nicht „wie viele“ sondern „welche“. Ein Test der alle Branches abdeckt ist besser als 10 Tests die nur Happy Path testen. Qualität über Quantität!

Frage 6: Coverage fällt nach Refactoring – normal?
Antwort: Ja! Mehr Code = mehr zu testen. Das ist OK. Wichtig: Neue Tests für neue Branches hinzufügen. Coverage-Trend wichtiger als absoluter Wert!

Frage 7: Was macht ihr bei persönlichen Problemen zwischen den Projekten?
Antwort: Das ist… kompliziert. Manche Geschichten gehören nicht in Tech-Blogs, sondern in private logs. Aber das ist ein anderes Kapitel. 🔒


📚 Die CI/CD-Serie im Überblick

✅ Bereits erschienen:

  • Teil 1 (24.10): Von Manual zu Pipeline
  • Teil 2 (31.10): Security Gates – OWASP & Trivy

👉 Du bist hier:

  • Teil 3 (07.11): Coverage Gates – JaCoCo & Test-Qualität

🔒 Demnächst:

  • Teil 4 (14.11): Quality Gates – SonarQube & Technical Debt
  • Teil 5-12: Container, Deployment, Enterprise…

Alle Teile: java-fleet.com/series/cicd


📥 Downloads & Ressourcen

Heute für dich:


🎓 Was du heute gelernt hast

Du kannst jetzt:

  • ✅ JaCoCo in Pipeline integrieren
  • ✅ Line, Branch, Complexity Coverage unterscheiden
  • ✅ Coverage-Reports richtig lesen
  • ✅ Sinnvolle Coverage-Thresholds setzen
  • ✅ Gute von schlechten Tests unterscheiden
  • ✅ Verstehen warum 147 grüne Tests Production killen können

Code Sentinel’s Fazit:

„Coverage-Prozente sind wie Likes auf Social Media – sehen gut aus, aber sagen nichts über Qualität. Branch Coverage ist mir wichtiger als Line Coverage. Und Tests mit Asserts sind mir wichtiger als beides zusammen.“

Anna fügt hinzu:

„Ich hatte 95% Coverage und dachte ich bin sicher. Jetzt habe ich 82% – aber die testen wirklich was. Seitdem: Kein Production-Incident mehr wegen ungetesteter Branches.“


🔮 Nächste Woche: Quality Gates

Teil 4 (14.11):

Quality Gates – SonarQube & Technical Debt

Wenn Tests grün sind, aber Code trotzdem Müll

Sarah aus Hamburg hat alle Tests grün, Coverage bei 85%, keine CVEs. Aber der Code? 147 Code Smells, Cyclomatic Complexity von 42, duplicate Code überall.

Nächste Woche lernst du:

  • SonarQube in GitHub Actions/Jenkins
  • Technical Debt messen und managen
  • Code Smells automatisch finden
  • Alle Quality-Tools zusammen nutzen (OWASP + Trivy + JaCoCo + SonarQube)

Lass uns Code-Quality automatisieren! 🎯


🎯 Community-Challenge: „Coverage Hero“

Die Challenge diese Woche:

  1. Integriere JaCoCo in deine Pipeline
  2. Finde einen Test ohne Asserts
  3. Fixe ihn (mit richtigen Asserts)
  4. Screenshot von Coverage-Report
  5. Teile mit #JavaFleetCoverage

Die besten 3 Stories:

  • 🏆 Feature im nächsten Post
  • 🎁 Coverage Cheat-Sheet (exclusive)
  • ⭐ Code-Review von Code Sentinel

Deadline: Nächsten Sonntag, 23:59 Uhr


💌 Bis nächste Woche!

Das war Teil 3 der CI/CD-Serie! Coverage verstanden – jetzt weißt du was deine Tests wirklich testen!

Zwischen den Zeilen: Manchmal fühlt sich Testing an wie Herz Schmerz – man gibt sich Mühe, aber Production crasht trotzdem. Aber hey, mit den richtigen Coverage-Gates wird’s besser! 💔

Neugierig geworden? Die Suche oben auf java-developer.online findet manchmal mehr als nur Tech-Content… 😉

Fragen? Tests ohne Asserts gefunden?

Schreib mir:

  • 📧 code.sentinel@java-fleet.com
  • 💬 Twitter: @CodeSentinelDev
  • 💼 LinkedIn: Code Sentinel

Teile deine Coverage-Erfolge mit #JavaFleetCoverage!

Wir sehen uns nächste Woche bei den Quality Gates. 🎯

— Code Sentinel

P.S. Anna hat jetzt 82% Coverage – aber die sind echt.
P.P.S. Kofi schreibt jetzt Tests mit Asserts. Progress!
P.P.P.S. Lisa? Nächste Woche ist ihre Geburtstagsparty. Hab ihr ein Buch über… Modelleisenbahnen gekauft. Smooth.


🎬 Bernd’s Corner

„Coverage-Prozente.

Endlich redet mal jemand Klartext.

Ich sage seit Jahren: 100% Coverage bedeutet nichts. 2007 hatte ich ein Projekt: 98% Coverage. Keine einzige Assertion.

Jetzt lernt ihr’s auch.

Und Branch Coverage? Das ist doch selbstverständlich. Wenn ihr nur Happy Path testet, dann testet ihr gar nichts.

Aber macht’s ruhig. Ich warte hier bis ihr’s rafft.

— Bernd, der schon Asserts schrieb als ihr noch println() als Test genutzt habt“


📊 Nächster Post: Quality Gates – Wenn Tests grün sind, aber Code trotzdem Müll
📅 Erscheint: Donnerstag, 14.11.2025, 09:00 Uhr
🔔 Newsletter: Hier anmelden


Tags: #CoverageGates #JaCoCo #TestQuality #BranchCoverage #CICD #Testing #QualityAssurance

Serie: CI/CD-Grundlagen | Modul 1: Foundations (Teil 3 von 4)

Autor

  • Code Sentinel

    32 Jahre alt, Technical Project Manager und Security-Experte bei Java Fleet Systems Consulting. Code ist ein erfahrener Entwickler, der in die Projektleitung aufgestiegen ist, aber immer noch tief in der Technik verwurzelt bleibt. Seine Mission: Sicherstellen, dass Projekte termingerecht, sicher und wartbar geliefert werden.