Code Coverage: Unterschied zwischen den Versionen

Aus FI-Wiki
 
(14 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt)
Zeile 1: Zeile 1:
== Code Coverage in Java ==
'''Code Coverage''' (Testabdeckung) gibt an, wie viel Prozent des Programmcodes während eines Tests tatsächlich ausgeführt wurde. 
Sie misst also, '''wie gut der vorhandene Code durch Tests abgedeckt ist''' und hilft einzuschätzen, ob wichtige Teile des Programms ausreichend getestet wurden.


=== Beispielcode ===
Eine hohe Code Coverage bedeutet nicht automatisch fehlerfreie Software, zeigt aber, dass viele Wege im Programm getestet wurden. 
Typische Messgrößen sind Anweisungsüberdeckung, Zweigüberdeckung und Pfadüberdeckung.
 
== Beispielcode ==


<syntaxhighlight lang="java">
<syntaxhighlight lang="java">
Zeile 18: Zeile 22:
Dieser Code hat zwei unabhängige if-Bedingungen: eine für x und eine für y.
Dieser Code hat zwei unabhängige if-Bedingungen: eine für x und eine für y.


=== 1. Anweisungsüberdeckung (Statement Coverage) ===
== Anweisungsüberdeckung (Statement Coverage) ==


Anweisungsüberdeckung bedeutet, dass '''jede''' Anweisung im Code mindestens einmal ausgeführt wird. In diesem Beispiel sind die Anweisungen:
Anweisungsüberdeckung bedeutet, dass '''jede''' Anweisung im Code mindestens einmal ausgeführt wird. In diesem Beispiel sind die Anweisungen:


# if (x > 0)
'''Bedingung 1''': if (x > 0)


# System.out.println("x ist positiv");
'''Anweisung 1''': System.out.println("x ist positiv");


# if (y > 0)
'''Bedingung 2''': (y > 0)


# System.out.println("y ist positiv");
'''Anweisung 2''': System.out.println("y ist positiv");


Das Ziel der Anweisungsüberdeckung ist es, sicherzustellen, dass jede dieser Anweisungen mindestens einmal aufgerufen wird.
Das Ziel der Anweisungsüberdeckung ist es, sicherzustellen, dass jede dieser Anweisungen mindestens einmal aufgerufen wird.
Zeile 43: Zeile 47:
* Ebenso wird die Bedingung y > 0 erfüllt, also wird System.out.println("y ist positiv") ausgeführt.
* Ebenso wird die Bedingung y > 0 erfüllt, also wird System.out.println("y ist positiv") ausgeführt.


=== 2. Zweigüberdeckung (Branch Coverage) ===
== Zweigüberdeckung (Branch Coverage) ==


Zweigüberdeckung bedeutet, dass jeder Zweig einer Bedingung '''mindestens einmal''' getestet wird (true und false).
Zweigüberdeckung bedeutet, dass jeder Zweig einer Bedingung '''mindestens einmal''' getestet wird (true und false).
Zeile 59: Zeile 63:
Damit sind alle Zweige (true/false) beider Bedingungen abgedeckt.
Damit sind alle Zweige (true/false) beider Bedingungen abgedeckt.


=== 3. Pfadüberdeckung (Path Coverage) ===
== Pfadüberdeckung (Path Coverage) ==


Pfadüberdeckung bedeutet, dass '''alle möglichen Kombinationen''' von Pfaden durch den Code getestet werden.
Pfadüberdeckung bedeutet, dass '''alle möglichen Kombinationen''' von Pfaden durch den Code getestet werden.
Zeile 66: Zeile 70:


# x > 0 und y > 0
# x > 0 und y > 0
# x > 0 und y <= 0
# x > 0 und y <= 0
# x <= 0 und y > 0
# x <= 0 und y > 0
# x <= 0 und y <= 0
# x <= 0 und y <= 0


Zeile 83: Zeile 84:
Mit diesen vier Testfällen decken wir alle möglichen Pfade durch den Code ab.
Mit diesen vier Testfällen decken wir alle möglichen Pfade durch den Code ab.


=== Unterschied zwischen Zweig- und Pfadüberdeckung ===
Bei Programmen mit Schleifen kann eine vollständige Pfadüberdeckung praktisch unmöglich sein, da durch unterschiedliche Schleifendurchläufe sehr viele oder sogar theoretisch unendlich viele Ausführungspfade entstehen können.
 
== Unterschied zwischen Zweig- und Pfadüberdeckung ==
 
* '''Zweigüberdeckung''' prüft nur, ob jeder Zweig der Bedingung (z.B. if- oder else-Zweig) mindestens einmal durchlaufen wurde. Die Testfälle beispielFunktion(-1, 1) und beispielFunktion(1, -1) erreichen dies.
 
* '''Pfadüberdeckung''' geht einen Schritt weiter und stellt sicher, dass jede Kombination der Bedingungen getestet wird. Hier sind zwei zusätzliche Testfälle (beispielFunktion(-1, -1), beispielFunktion(1, 1)) notwendig, um den Pfad x <= 0 und y <= 0 , sowie x > 0 und y > 0 zu testen. Diese Pfade werden bei der reinen Zweigüberdeckung nicht getestet.
 
== Äquivalenzklassenbildung ==
 
Die '''Äquivalenzklassenbildung''' ist ein Testverfahren, bei dem Eingabewerte in Gruppen ([[Äquivalenzklassen]]) eingeteilt werden. 
Alle Werte einer Klasse verhalten sich aus Sicht des Programms gleich, sodass es ausreicht, nur einen repräsentativen Wert pro Klasse zu testen.
 
=== Ziel ===
 
* Reduzierung der Anzahl an Testfällen 
* trotzdem gute Testabdeckung 
* systematisches Testen von Eingaben 
 
=== Anwendung auf das Beispiel ===
 
Die Funktion prüft die Bedingungen:
 
* x > 0 
* y > 0 
 
Daraus ergeben sich folgende Äquivalenzklassen:
 
'''Für x:'''
* Äquivalenzklasse 1: x > 0
* Äquivalenzklasse 2: x <= 0
 
'''Für y:'''
* Äquivalenzklasse 1: y > 0
* Äquivalenzklasse 2: y <= 0
 
=== Testfälle aus Äquivalenzklassen ===
 
Werden die Äquivalenzklassen von x und y miteinander kombiniert, ergeben sich vier mögliche Kombinationen:
 
<syntaxhighlight lang="java">
Beispiel.beispielFunktion(1, 1);    // beide positiv
Beispiel.beispielFunktion(1, -1);  // x positiv, y nicht
Beispiel.beispielFunktion(-1, 1);  // x nicht, y positiv
Beispiel.beispielFunktion(-1, -1);  // beide nicht positiv
</syntaxhighlight>
 
=== Zusammenhang zur Pfadüberdeckung ===
 
Werden alle Äquivalenzklassen von x und y miteinander kombiniert, führen sie in diesem einfachen Beispiel zu denselben vier Testfällen wie die vollständige Pfadüberdeckung. Das ist jedoch nicht grundsätzlich der Fall.


* '''Zweigüberdeckung''' prüft nur, ob jeder Zweig der Bedingung (z.B. if- oder else-Zweig) mindestens einmal durchlaufen wurde. Die Testfälle für Zweigüberdeckung beispielFunktion(-1, 1), beispielFunktion(1, -1)) erreichen dies.
=== Kurzmerksatz ===


* '''Pfadüberdeckung''' geht einen Schritt weiter und stellt sicher, dass jede Kombination der Bedingungen getestet wird. Hier sind zwei zusätzliche Testfälle (beispielFunktion(-1, -1), beispielFunktion(1, 1)) notwendig, um den Pfad x <= 0 und y <= 0 , sowie x >= 0 und y >= 0 zu testen. Diese Pfade werden bei der reinen Zweigüberdeckung nicht getestet.
'''Äquivalenzklassen fassen ähnliche Eingaben zusammen, sodass weniger, aber gezielte Testfälle benötigt werden.'''


=== Fazit ===
== Fazit ==


* '''Anweisungsüberdeckung:''' 1 Testfall reicht aus, wenn alle Anweisungen mindestens einmal ausgeführt werden (z. B. beispielFunktion(1, 1))
* '''Zweigüberdeckung:''' Du kannst 100% Zweigüberdeckung mit 2 Testfällen erreichen, da beide Zweige jeder Bedingung (true/false) getestet werden.
* '''Zweigüberdeckung:''' Du kannst 100% Zweigüberdeckung mit 2 Testfällen erreichen, da beide Zweige jeder Bedingung (true/false) getestet werden.
* '''Pfadüberdeckung:''' Du benötigst 4 Testfälle, um alle Kombinationen der Bedingungen (also alle Pfade) zu testen.
* '''Pfadüberdeckung:''' Du benötigst 4 Testfälle, um alle Kombinationen der Bedingungen (also alle Pfade) zu testen.

Aktuelle Version vom 29. September 2026, 11:28 Uhr

Code Coverage (Testabdeckung) gibt an, wie viel Prozent des Programmcodes während eines Tests tatsächlich ausgeführt wurde. Sie misst also, wie gut der vorhandene Code durch Tests abgedeckt ist und hilft einzuschätzen, ob wichtige Teile des Programms ausreichend getestet wurden.

Eine hohe Code Coverage bedeutet nicht automatisch fehlerfreie Software, zeigt aber, dass viele Wege im Programm getestet wurden. Typische Messgrößen sind Anweisungsüberdeckung, Zweigüberdeckung und Pfadüberdeckung.

Beispielcode

public class Beispiel {
    public static void beispielFunktion(int x, int y) {
        if (x > 0) {
            System.out.println("x ist positiv");
        }        
        if (y > 0) {
            System.out.println("y ist positiv");
        }
    }
}

Dieser Code hat zwei unabhängige if-Bedingungen: eine für x und eine für y.

Anweisungsüberdeckung (Statement Coverage)

Anweisungsüberdeckung bedeutet, dass jede Anweisung im Code mindestens einmal ausgeführt wird. In diesem Beispiel sind die Anweisungen:

Bedingung 1: if (x > 0)

Anweisung 1: System.out.println("x ist positiv");

Bedingung 2: (y > 0)

Anweisung 2: System.out.println("y ist positiv");

Das Ziel der Anweisungsüberdeckung ist es, sicherzustellen, dass jede dieser Anweisungen mindestens einmal aufgerufen wird.

Testfall für 100% Anweisungsüberdeckung:

Beispiel.beispielFunktion(1, 1);  // x > 0, y > 0

Erklärung:

  • Bei beispielFunktion(1, 1) wird die Bedingung x > 0 erfüllt, also wird System.out.println("x ist positiv") ausgeführt.
  • Ebenso wird die Bedingung y > 0 erfüllt, also wird System.out.println("y ist positiv") ausgeführt.

Zweigüberdeckung (Branch Coverage)

Zweigüberdeckung bedeutet, dass jeder Zweig einer Bedingung mindestens einmal getestet wird (true und false).

  • if (x > 0): true / false
  • if (y > 0): true / false

Testfälle für 100% Zweigüberdeckung:

Beispiel.beispielFunktion(-1, 1);  // x <= 0, y > 0
Beispiel.beispielFunktion(1, -1);  // x > 0, y <= 0

Damit sind alle Zweige (true/false) beider Bedingungen abgedeckt.

Pfadüberdeckung (Path Coverage)

Pfadüberdeckung bedeutet, dass alle möglichen Kombinationen von Pfaden durch den Code getestet werden.

Mögliche Pfade:

  1. x > 0 und y > 0
  2. x > 0 und y <= 0
  3. x <= 0 und y > 0
  4. x <= 0 und y <= 0

Testfälle für 100% Pfadüberdeckung:

Beispiel.beispielFunktion(1, 1);    // Pfad 1
Beispiel.beispielFunktion(1, -1);   // Pfad 2
Beispiel.beispielFunktion(-1, 1);   // Pfad 3
Beispiel.beispielFunktion(-1, -1);  // Pfad 4

Mit diesen vier Testfällen decken wir alle möglichen Pfade durch den Code ab.

Bei Programmen mit Schleifen kann eine vollständige Pfadüberdeckung praktisch unmöglich sein, da durch unterschiedliche Schleifendurchläufe sehr viele oder sogar theoretisch unendlich viele Ausführungspfade entstehen können.

Unterschied zwischen Zweig- und Pfadüberdeckung

  • Zweigüberdeckung prüft nur, ob jeder Zweig der Bedingung (z.B. if- oder else-Zweig) mindestens einmal durchlaufen wurde. Die Testfälle beispielFunktion(-1, 1) und beispielFunktion(1, -1) erreichen dies.
  • Pfadüberdeckung geht einen Schritt weiter und stellt sicher, dass jede Kombination der Bedingungen getestet wird. Hier sind zwei zusätzliche Testfälle (beispielFunktion(-1, -1), beispielFunktion(1, 1)) notwendig, um den Pfad x <= 0 und y <= 0 , sowie x > 0 und y > 0 zu testen. Diese Pfade werden bei der reinen Zweigüberdeckung nicht getestet.

Äquivalenzklassenbildung

Die Äquivalenzklassenbildung ist ein Testverfahren, bei dem Eingabewerte in Gruppen (Äquivalenzklassen) eingeteilt werden. Alle Werte einer Klasse verhalten sich aus Sicht des Programms gleich, sodass es ausreicht, nur einen repräsentativen Wert pro Klasse zu testen.

Ziel

  • Reduzierung der Anzahl an Testfällen
  • trotzdem gute Testabdeckung
  • systematisches Testen von Eingaben

Anwendung auf das Beispiel

Die Funktion prüft die Bedingungen:

  • x > 0
  • y > 0

Daraus ergeben sich folgende Äquivalenzklassen:

Für x:

  • Äquivalenzklasse 1: x > 0
  • Äquivalenzklasse 2: x <= 0

Für y:

  • Äquivalenzklasse 1: y > 0
  • Äquivalenzklasse 2: y <= 0

Testfälle aus Äquivalenzklassen

Werden die Äquivalenzklassen von x und y miteinander kombiniert, ergeben sich vier mögliche Kombinationen:

Beispiel.beispielFunktion(1, 1);    // beide positiv
Beispiel.beispielFunktion(1, -1);   // x positiv, y nicht
Beispiel.beispielFunktion(-1, 1);   // x nicht, y positiv
Beispiel.beispielFunktion(-1, -1);  // beide nicht positiv

Zusammenhang zur Pfadüberdeckung

Werden alle Äquivalenzklassen von x und y miteinander kombiniert, führen sie in diesem einfachen Beispiel zu denselben vier Testfällen wie die vollständige Pfadüberdeckung. Das ist jedoch nicht grundsätzlich der Fall.

Kurzmerksatz

Äquivalenzklassen fassen ähnliche Eingaben zusammen, sodass weniger, aber gezielte Testfälle benötigt werden.

Fazit

  • Anweisungsüberdeckung: 1 Testfall reicht aus, wenn alle Anweisungen mindestens einmal ausgeführt werden (z. B. beispielFunktion(1, 1))
  • Zweigüberdeckung: Du kannst 100% Zweigüberdeckung mit 2 Testfällen erreichen, da beide Zweige jeder Bedingung (true/false) getestet werden.
  • Pfadüberdeckung: Du benötigst 4 Testfälle, um alle Kombinationen der Bedingungen (also alle Pfade) zu testen.


Pfadüberdeckung ist strenger, da sie jede mögliche Ausführungskombination abdeckt.