Zyklomatische Komplexität beim Softwaretesten mit Beispiel

⚡ Intelligente Zusammenfassung

Die zyklomatische Komplexität ist eine Softwaremetrik, die 1976 von Thomas McCabe entwickelt wurde und die unabhängigen Pfade durch ein Programm zählt. Sie wird aus einem Kontrollflussgraphen berechnet und gibt die Anzahl der Testfälle an, die für eine vollständige Zweigabdeckung erforderlich sind.

  • 📐 Zwei Formeln: V(G) = E – N + 2 aus dem Graphen, oder V(G) = P + 1 aus der Anzahl der Entscheidungspunkte.
  • 🧮 Direkte Bedeutung: Der Wert entspricht der maximalen Anzahl unabhängiger Pfade und damit der Anzahl der benötigten Testfälle.
  • 🗺️ Graphische Grundlage: Knoten repräsentieren Verarbeitungsschritte und Kanten den Kontrollfluss zwischen ihnen.
  • 🟢 1 zu 10: Strukturierter, gut geschriebener Code mit hoher Testbarkeit und geringem Wartungsaufwand.
  • 🟠 21 zu 40: Sehr komplexer Code mit geringer Testbarkeit, bei dem Refactoring in der Regel weniger kostet als Testen.
  • Werkzeug: SonarQube, Visual Studio Code Metrics, Radon und Lizard berechnen es automatisch.

Zyklomatische Komplexität beim Softwaretesten

Was ist McCabes zyklomatische Komplexität?

Zyklomatische Komplexität beim Softwaretesten ist eine Testmetrik, die zur Messung der Komplexität eines Softwareprogramms verwendet wird. Es ist ein quantitatives Maß für unabhängige Pfade im Quellcode eines Softwareprogramms. Die zyklomatische Komplexität kann mithilfe von Kontrollflussdiagrammen oder in Bezug auf Funktionen, Module, Methoden oder Klassen innerhalb eines Softwareprogramms berechnet werden.

Ein unabhängiger Pfad ist als ein Pfad definiert, der mindestens eine Kante hat, die zuvor noch von keinem anderen Pfad durchlaufen wurde.

Diese Metrik wurde 1976 von Thomas J. McCabe entwickelt und basiert auf einer Kontrollflussdarstellung des Programms. Der Kontrollfluss stellt ein Programm als Diagramm dar, das aus Knoten und Kanten besteht.

Im Diagramm stellen Knoten Verarbeitungsaufgaben dar, während Kanten den Kontrollfluss zwischen den Knoten darstellen.

McCabes zyklomatische Komplexität

Flussdiagrammnotation für ein Programm

Die Flussdiagramm-Notation für ein Programm definiert mehrere Knoten, die durch die Kanten verbunden sind. Nachfolgend finden Sie Flussdiagramme für Anweisungen wie if-else, While, Until und die normale Flusssequenz.

Flussdiagramm-Notation für ein Programm

So berechnen Sie die zyklomatische Komplexität

Mathematische Darstellung:

Mathematisch gesehen handelt es sich um eine Menge unabhängiger Pfade durch das Graphdiagramm. Code Die Komplexität des Programms kann mithilfe der folgenden Formel definiert werden:

V(G) = E - N + 2

Woher,

E – Anzahl der Kanten

N – Anzahl der Knoten

V (G) = P + 1

Wobei P = Anzahl der Prädikatknoten (Knoten, der die Bedingung enthält)

Beispiel -

i = 0;
n=4; //N-Number of nodes present in the graph

while (i<n-1) do
j = i + 1;

while (j<n) do

if A[i]<A[j] then
swap(A[i], A[j]);

end do;
j=j+1;

end do;

Das Flussdiagramm für dieses Programm wird sein

Zyklomatische Komplexität berechnen

Mathematisch rechnen,

  • V(G) = 9 – 7 + 2 = 4
  • V(G) = 3 + 1 = 4 (Bedingungsknoten sind 1,2 und 3 Knoten)

Basissatzdie vier unabhängigen Ausführungspfade:

  • 1, 7
  • 1, 2, 6, 1, 7
  • 1, 2, 3, 4, 5, 2, 6, 1, 7
  • 1, 2, 3, 5, 2, 6, 1, 7

Eigenschaften der zyklomatischen Komplexität

Im Folgenden sind die Eigenschaften der zyklomatischen Komplexität aufgeführt:

  1. V (G) ist die maximale Anzahl unabhängiger Pfade im Diagramm
  2. V (G) >=1
  3. G hat einen Weg, wenn V (G) = 1
  4. Eine gängige Richtlinie ist, V(G) für ein einzelnes Modul bei 10 oder darunter zu halten.

Wie diese Metrik für Softwaretests nützlich ist

Basispfad-Tests gehören zu den White-Box-Testverfahren und garantieren die Ausführung mindestens einer Anweisung während des Tests. Sie überprüfen jeden linear unabhängigen Pfad durch das Programm, was bedeutet, dass Die Anzahl der benötigten Testfälle entspricht der zyklomatischen Komplexität des Programms..

Diese Metrik ist nützlich aufgrund der Eigenschaften der zyklomatischen Komplexität (M) –

  1. M kann die Anzahl der Testfälle sein, um eine Zweigabdeckung zu erreichen (Obergrenze).
  2. M kann die Anzahl der Pfade durch die Graphen sein. (Untergrenze)

Betrachten Sie dieses Beispiel –

If (Condition 1)
Statement 1

Else
Statement 2

If (Condition 2)
Statement 3

Else
Statement 4

Die zyklomatische Komplexität für dieses Programm beträgt 8-7+2=3.

Da die Komplexität mit 3 berechnet wurde, sind drei Testfälle erforderlich, um die vollständige Pfad-Abdeckung für das obige Beispiel sicherzustellen.

Zu befolgende Schritte

Zur Berechnung der zyklomatischen Komplexität und zum Entwurf von Testfällen sollten die folgenden Schritte befolgt werden.

Schritt 1: – Konstruktion eines Diagramms mit Knoten und Kanten aus dem Code

Schritt 2: – Identifizierung unabhängiger Pfade

Schritt 3: – Zyklomatische Komplexitätsberechnung

Schritt 4: – Design von Testfällen

Sobald der Grundsatz gebildet ist, TESTFÄLLE sollte geschrieben werden, um alle Pfade auszuführen.

Mehr zu V (G)

Die zyklomatische Komplexität kann manuell berechnet werden, wenn das Programm klein ist. Bei sehr komplexen Programmen müssen automatisierte Tools verwendet werden, da diese mehr Flussdiagramme beinhalten. Basierend auf der Komplexitätszahl kann das Team Rückschlüsse auf die Maßnahmen ziehen, die zur Messung ergriffen werden müssen.

Die folgende Tabelle gibt einen Überblick über die Komplexitätszahl und die entsprechende Bedeutung von v (G):

Komplexitätszahl Bedeutung
1 bis 10

Strukturierter und gut geschriebener Code

Hohe Testbarkeit

Kosten und Aufwand sind geringer

11 bis 20

Komplexer Code

Mittlere Testbarkeit

Kosten und Aufwand sind mittel.

21 bis 40

Sehr komplexer Code

Geringe Testbarkeit

Kosten und Aufwand sind hoch

> 40

Überhaupt nicht prüfbar

Sehr hoher Kosten- und Arbeitsaufwand

Werkzeuge zur Berechnung der zyklomatischen Komplexität

Es stehen viele Tools zur Verfügung, um die Komplexität der Anwendung zu bestimmen. Einige Tools zur Komplexitätsberechnung werden für bestimmte Technologien verwendet. Die Komplexität kann anhand der Anzahl der Entscheidungspunkte in einem Programm ermittelt werden. Die Entscheidungspunkte sind if-, for-, for-each-, while-, do-, catch- und case-Anweisungen in einem Quellcode.

Beispiele für Werkzeuge sind

  • OCLint – Statischer Code-Analysator für C und verwandte Sprachen
  • SonarQube – Berichtet über zyklomatische und kognitive Komplexität in mehr als 25 Sprachen
  • Visual Studio Code Metriken – Integrierte zyklomatische Komplexitätsanalyse für .NET-Assemblies
  • Radon und Lizard – Kommandozeilen-Komplexitätsanalysatoren für Python und für mehrsprachige Projekte bzw.
  • GMetrics – Finden Sie Metriken in Java verwandte Anwendungen

Anwendungen der zyklomatischen Komplexität

Die zyklomatische Komplexität kann sehr hilfreich sein bei

  • Hilft Entwicklern und Testern, unabhängige Pfadausführungen zu bestimmen
  • Die Entwickler können gewährleisten, dass alle Pfade mindestens einmal getestet wurden.
  • Hilft uns, uns mehr auf die unentdeckten Wege zu konzentrieren
  • Verbessern Sie die Codeabdeckung in Software Engineering
  • Bewerten Sie das mit der Anwendung oder dem Programm verbundene Risiko
  • Die Verwendung dieser Kennzahlen zu Beginn des Zyklus verringert das Risiko des Programms

Wie man die zyklomatische Komplexität reduziert

Eine hohe Komplexitätszahl ist ein Signal, kein Urteil. Vier Refaktorierungen tragen maßgeblich zur in der Praxis erzielbaren Reduzierung bei.

  • Extract-Methode. Das Auslagern eines Zweigs in eine eigene Funktion verteilt die Komplexität auf zwei Module. Die Gesamtkomplexität des Systems bleibt unverändert, aber jede Einheit ist nun unabhängig testbar.
  • Ersetzen Sie eine bedingte Kette durch eine Nachschlagetabelle. Eine lange if-else-if-Kette, die dieselbe Variable prüft, wird zu einer Map oder einem Switch, wodurch viele Entscheidungspunkte zu einem einzigen zusammengefasst werden.
  • Verwenden Sie Schutzklauseln. Durch die frühzeitige Rückgabe bei ungültiger Eingabe wird die Verschachtelung, die ein einzelner großer if-else-Block erzeugt, beseitigt, ohne das Verhalten zu ändern.
  • Ersetze bedingte Anweisungen durch Polymorphismus. Wenn eine Bedingung auf einem Typ basiert, entfällt die Entscheidung vollständig, wenn jeder Zweig in eine eigene Klasse verschoben wird.

Vorher, mit V(G) = 4:

if (user != null) {
    if (user.isActive()) {
        if (user.hasRole("admin")) {
            return grantAccess();
        }
    }
}
return denyAccess();

Anschließend, bei gleichem Verhalten und nach Entfernung der Verschachtelung:

if (user == null) return denyAccess();
if (!user.isActive()) return denyAccess();
if (!user.hasRole("admin")) return denyAccess();
return grantAccess();

Ein Hinweis zur Messgröße. Die zyklomatische Komplexität misst Entscheidungen, nicht deren Schwierigkeit. Eine Switch-Anweisung mit zwanzig einfachen Fällen erreicht einen Wert von 21 und ist dennoch leicht lesbar, während ein tief verschachtelter Block mit einem Wert von 8 deutlich schwerer verständlich sein kann. Nutzen Sie diesen Wert, um Kandidaten für eine Überprüfung zu finden, nicht als Ziel für Manipulationen.

Häufig gestellte Fragen

Als Richtwert gelten zehn oder weniger Codezeilen pro Modul. Bei elf bis 20 ist der Code zwar komplex, aber noch handhabbar. Ab 20 Codezeilen nimmt die Testbarkeit rapide ab, und ab 40 Codezeilen gilt das Modul in der Regel als in seiner jetzigen Form nicht testbar.

Beide Methoden liefern dasselbe Ergebnis. P + 1 ist bei manueller Berechnung schneller, da nur die Entscheidungspunkte gezählt werden. Tools verwenden E – N + 2, da sie den Kontrollflussgraphen bereits erstellen.

Nicht unbedingt. Die zyklomatische Komplexität misst Entscheidungen, nicht deren Schwierigkeitsgrad. Daher erzielt ein einfacher Switch mit zwanzig Fällen eine hohe Punktzahl und bleibt gleichzeitig gut lesbar. Betrachten Sie die Zahl als Anstoß zur Überprüfung.

Sie kombinieren dies mit der Änderungshäufigkeit und der Fehlerhistorie, um zu ermitteln, welche Module das größte Risiko bergen, und konzentrieren die Überprüfungs- und Testbemühungen auf den Code, der am ehesten fehlschlagen wird.

Ja. KI-Assistenten schlagen Schutzklauseln vor, z. B.tracVerwenden Sie Methoden und Nachschlagetabellen, um die Anzahl zu reduzieren. Überprüfen Sie das Verhalten mit der bestehenden Testsuite, da eine Refaktorisierung, die die Logik ändert, den Zweck zunichtemacht.

Fassen Sie diesen Beitrag mit folgenden Worten zusammen: