Parasoft C/C++test 2022.2 unterstützt das neue MISRA C:2012 Amendment 3 und eine Entwurfsversion von MISRA C++ 202x. Erfahren Sie mehr >>

JUnit Automatisierte Testfallgenerierung und Codeabdeckung

Von Arthur Hicken

16. März 2018

6  min lesen

Wenn die Codeabdeckung für Sie ein Problem darstellt, stellen Sie sicher, dass Sie sie richtig messen und alles anhand aller von Ihnen durchgeführten Tests messen. Nutzen Sie die automatische Testfallgenerierung für die JUnit-Codeabdeckung, um Ihre Tests schnell zu erstellen und zu erweitern und eine aussagekräftige, wartbare vollständige Codeabdeckung zu erhalten. Die Abdeckung durch Unit-Tests ist eine hervorragende Möglichkeit, um sicherzustellen, dass Sie alles richtig messen.

Tiefes Eintauchen in Probleme und Lösungen der Codeabdeckung

Ich schrieb vor kurzem über wie einfach es ist, in die Falle zu tappen, wenn es darum geht, Prozentsätze der Codeabdeckung zu verfolgenDies führte zu Qualitätsdiskussionen, und ich dachte, ich würde mich eingehender mit Problemen und Lösungen der Codeabdeckung befassen. Insbesondere die Abdeckungsnummer selbst, der Wert automatisch generierter JUnit-Tests und die Art und Weise, wie Sie Unit-Tests identifizieren können, bei denen Probleme auftreten. Und wie man mit der Ausführung einen besseren Job macht.

Wie funktioniert die JUnit-Code-Abdeckung?

Beginnen wir mit der Abdeckungsmetrik selbst und wie wir die Codeabdeckung zählen. Code-Coverage-Nummern sind oft bedeutungslos oder bestenfalls irreführend. Was bedeutet es überhaupt, wenn Sie eine 100% ige Codeabdeckung haben? Wie haben Sie es gemessen?

Es gibt viele verschiedene Methoden, um die Abdeckung zu messen.

Eine Möglichkeit, die Codeabdeckung zu messen, besteht aus der Sicht der Anforderungen. Haben Sie einen Test für jede Anforderung? Dies ist ein vernünftiger Anfang… aber es bedeutet nicht, dass der gesamte Code getestet wurde.

Eine andere Möglichkeit, die Codeabdeckung zu messen (nicht lachen, das höre ich tatsächlich in der realen Welt), ist die Anzahl der bestandenen Tests. Wirklich, ich meine es ernst! Dies ist eine ziemlich schreckliche Metrik und offensichtlich bedeutungslos. Ist es schlimmer oder besser, als nur zu zählen, wie viele Tests Sie haben? Ich konnte es nicht sagen.

Dann versuchen wir festzustellen, welcher Code ausgeführt wurde. Zu den allgemeinen Abdeckungsmetriken gehören Kontoauszugsabdeckung, Leitungsabdeckung, Zweigabdeckung, Entscheidungsabdeckung, Abdeckung mit mehreren Bedingungen oder die umfassendere MC / DC or Geänderte Bedingung / Entscheidungsabdeckung.

Die einfachste Methode ist natürlich die Linienabdeckung, aber wie Sie wahrscheinlich gesehen haben, messen Tools dies unterschiedlich, sodass die Abdeckung unterschiedlich sein wird. Das Ausführen von Codezeilen bedeutet nicht, dass Sie alle verschiedenen Dinge überprüft haben, die in dieser Codezeile passieren können. Deshalb mögen sicherheitskritische Standards ISO 26262 für die funktionale Sicherheit von Kraftfahrzeugen und DO-178B / C. Für luftgestützte Systeme ist MC / DC erforderlich.

Hier ist ein einfaches Codebeispiel unter der Annahme, dass x, y und z Boolesche Werte sind:

If ((x || y) && z) {doSomethingGood (); } else {doSomethingElse ();}

In diesem Fall wurde die Linie unabhängig von meinen Werten „abgedeckt“. Zugegeben, dies ist eine schlampige Art zu codieren, indem alles in eine Zeile gesetzt wird, aber Sie sehen das Problem. Und die Leute schreiben tatsächlich Code auf diese Weise. Aber lassen Sie es uns ein bisschen aufräumen.

If ((x || y) && z) {
doSomethingGood ();
} Else {
mach etwas anderes(); / * weil Code niemals etwas tun sollteSomethingBad () * /

Ein einfacher Blick könnte mich zu dem Schluss führen, dass ich nur zwei Tests benötige - einen, der den gesamten Ausdruck auf WAHR auswertet und ausführt doSomethingGood () (x = wahr, y = wahr, z = wahr)und ein weiterer Test, der als FALSE ausgewertet und ausgeführt wird doSomethingElse () (x = falsch, y = falsch, z = falsch). Laut Leitungsabdeckung können wir loslegen: „Alles wurde getestet.“

Aber Moment mal, es gibt verschiedene Möglichkeiten, wie der Hauptausdruck getestet werden kann:

Wert von x Wert von y Wert von z Wert der Entscheidung
falsch falsch Wahre falsch
falsch Wahre Wahre Wahre
falsch Wahre falsch falsch
Wahre falsch Wahre Wahre

Dies ist ein einfaches Beispiel, aber es veranschaulicht den Punkt. Ich brauche hier 4 Tests, um den Code wirklich richtig abzudecken, zumindest wenn mir die MC / DC-Abdeckung wichtig ist. Die Leitungsabdeckung hätte 100% gesagt, als ich zur Hälfte fertig war. Ich werde die längere Erklärung über den Wert von MC / DC für ein anderes Mal belassen. Der Punkt hier ist, dass unabhängig davon, mit welcher Methode Sie die Abdeckung messen, es wichtig ist, dass das, was Sie durch Behauptungen validieren, von Bedeutung ist.

Verbessern Sie Unit-Tests für Java mit Automatisierung: Best Practices für Java-Entwickler

Sinnlose automatische Generierung

Eine weitere Falle, in die viele geraten, ist das Hinzufügen eines nicht anspruchsvollen Tools zum automatischen Generieren von Komponententests.

Einfache Tools zur Testgenerierung erstellen Tests, die Code ohne Zusicherungen ausführen. Dies verhindert, dass die Tests laut werden, aber alles, was es wirklich bedeutet, ist, dass Ihre Anwendung nicht abstürzt. Leider sagt Ihnen dies nicht, ob die Anwendung das tut, was sie soll, was sehr wichtig ist.

Bild des Mannes, der Treppen hochläuft, hergestellt von einem Dollarschein mit Falten, die zu einem großen Prozentzeichen führen.

Bei der nächsten Werkzeuggeneration werden Zusicherungen erstellt, die auf bestimmten Werten basieren, die automatisch erfasst werden können. Wenn die automatische Generierung jedoch eine Menge Behauptungen erstellt, entsteht eine Menge Rauschen. Hier gibt es keinen Mittelweg. Sie haben entweder etwas, das leicht zu warten, aber bedeutungslos ist, oder einen Wartungsalptraum, der von fragwürdigem Wert ist.

Viele Open-Source-Tools, die automatisch Komponententests generieren, sehen zunächst wertvoll aus, da Ihre Abdeckung sehr schnell steigt. In der Wartung treten die eigentlichen Probleme auf. Während der Entwicklung werden Entwickler häufig zusätzliche Anstrengungen unternehmen, um die automatisch generierten Zusicherungen zu optimieren und eine ihrer Meinung nach saubere Testsuite zu erstellen. Die Behauptungen sind jedoch spröde und passen sich nicht an, wenn sich der Code ändert. Dies bedeutet, dass Entwickler bei der nächsten Veröffentlichung einen Großteil der "automatischen" Generation erneut ausführen müssen. Testsuiten sollen wiederverwendet werden. Wenn Sie sie nicht wiederverwenden können, machen Sie etwas falsch.

Dies deckt auch nicht die beängstigendere Idee ab, dass im ersten Durchlauf bei hoher Abdeckung die Aussagen in den Tests weniger aussagekräftig sind, als sie sein sollten. Nur weil etwas behauptet werden kann, heißt das nicht, dass es sein sollte oder dass es sogar das Richtige ist.

öffentliche Klasse ListTest {
private Liste list = new ArrayList <> ();
@Prüfung
public void testAdd () {
list.add ("Foo");
assertNotNull (Liste);
}
}

Im Idealfall überprüft die Zusicherung, ob der Code ordnungsgemäß funktioniert, und die Zusicherung schlägt fehl, wenn der Code nicht ordnungsgemäß funktioniert. Es ist wirklich einfach, eine Reihe von Behauptungen zu haben, die beides nicht tun, was wir weiter unten untersuchen werden.

Rohabdeckung Vs. Sinnvolle Tests

Wenn Sie auf Kosten einer soliden, aussagekräftigen und sauberen Testsuite nach einer Nummer mit hoher Reichweite suchen, verlieren Sie an Wert. Eine gut gepflegte Testsuite gibt Ihnen Vertrauen in Ihren Code und ist sogar die Grundlage für ein schnelles und sicheres Refactoring. Laut und / oder bedeutungslose Tests bedeuten, dass Sie sich nicht auf Ihre Testsuite verlassen können, nicht für das Refactoring und nicht einmal für die Veröffentlichung.

Was passiert, wenn Leute ihren Code messen, insbesondere an strengen Standards, ist, dass sie herausfinden, dass sie niedriger sind, als sie sein wollen. Und oft endet dies damit, dass sie der Deckungsnummer nachjagen. Lassen Sie uns die Berichterstattung verbessern! Und jetzt können Sie gefährliches Gebiet betreten, indem Sie entweder unvernünftig davon ausgehen, dass automatisierte JUnit-Tests aussagekräftige Tests erstellt haben, oder indem Sie von Hand Komponententests erstellen, die wenig Bedeutung haben und deren Wartung teuer ist.

In der realen Welt überwiegen die laufenden Kosten für die Wartung einer Testsuite bei weitem die Kosten für die Erstellung von Komponententests. Daher ist es wichtig, dass Sie zu Beginn gute saubere Komponententests erstellen. Sie wissen dies, weil Sie die Tests im Rahmen Ihres CI-Prozesses (Continuous Integration) jederzeit ausführen können. Wenn Sie die Tests nur bei der Veröffentlichung ausführen, ist dies ein Zeichen dafür, dass die Tests lauter sind, als sie sein sollten. Und ironischerweise macht dies die Tests noch schlimmer, weil sie nicht gewartet werden.

Die Automatisierung von Softwaretests ist nicht schlecht - in der Tat ist sie angesichts der Komplexität und des Zeitdrucks, die heutzutage üblich sind, notwendig. Die automatische Generierung von Werten ist jedoch in der Regel mühsamer als es wert ist. Automatisierung, die auf der Erweiterung von Werten, der Überwachung realer Systeme und der Erstellung komplexer Frameworks, Mocks und Stubs basiert, bietet mehr Wert als die sinnlose Erstellung von Behauptungen.

Was kannst du tun?

Messen

Der erste Schritt besteht darin, Ihre aktuelle Berichterstattung zu messen und einen Bericht darüber zu erhalten. Andernfalls wissen Sie nicht, wo Sie sich befinden und ob es Ihnen besser geht. Es ist wichtig, dabei alle Testaktivitäten zu messen, einschließlich Einheit, Funktion, Handbuch usw., und die Abdeckung ordnungsgemäß zu aggregieren. Auf diese Weise werden Sie Ihre Anstrengungen dort einsetzen, wo es den größten Wert hat - auf Code, der überhaupt nicht getestet wird, und nicht auf Code, der von Ihren End-to-End-Tests abgedeckt wird, aber zufällig keinen hat Gerätetest. Parasoft kann die Codeabdeckung aus mehreren Läufen und mehreren Testarten genau aggregieren, um Ihnen ein genaues Maß dafür zu geben, wo Sie sich befinden. Weitere Informationen hierzu finden Sie in unserem Whitepaper.

Umfassende Codeabdeckung: Gesamtabdeckung über Testpraktiken hinweg

Frameworks

Tools, die Unit-Test-Skelette für Sie erstellen, sind ein guter Anfang. Stellen Sie sicher, dass diese Tools mit gängigen Mocking-Frameworks wie Mockito und PowerMock verbunden sind, da echter Code kompliziert ist und Stubbing und Mocking erfordert. Aber das reicht nicht - Sie müssen in der Lage sein:

  • Erstellen Sie sinnvolle Verspottungen
  • Erweitern Sie einfache Tests mit größeren, breiteren Daten
  • Überwachen Sie eine laufende Anwendung

Intelligente Unterstützung

Sie können all diese Dinge manuell tun, aber es kostet zu viel Zeit und Mühe. Dies ist ein ausgezeichneter Ort, um die Automatisierung zu nutzen – zum Beispiel, Unit-Testing-Lösung von Parasoft bietet automatische Empfehlungen in Echtzeit in der IDE und integriert sich in Open-Source-Frameworks (JUnit, Mockito, PowerMock usw.), um den Benutzer bei der Erstellung, Skalierung und Wartung seiner JUnit-Testsuite zu unterstützen und eine breitere Abdeckung bereitzustellen. Wenn Sie neugierig auf diese Technologie sind, können Sie mehr darüber erfahren, warum Menschen Komponententests hassen und wie man die Liebe zurückbringt.

Zusammenfassung

Wenn die Abdeckung ein Problem für Ihr Projekt darstellt, stellen Sie sicher, dass Sie es richtig messen und ALLES anhand aller von Ihnen durchgeführten Tests messen. Wenn Sie Ihre Abdeckung mit Komponententests erweitern, können Sie die geführte Testerstellung nutzen, um Ihre Tests schnell zu erstellen und zu erweitern und eine aussagekräftige, wartbare Codeabdeckung zu erhalten. Parasoft Jtest erstellt Tests, die gewartet werden können, wenn Ihr Code wächst und sich ändert, sodass Sie nicht immer wieder dieselbe Arbeit ausführen.

 

Automatisieren Sie die Erstellung von Junit-Tests und beginnen Sie, Unit-Tests zu lieben.
Probieren Sie Parasoft Jtest jetzt aus

Von Arthur Hicken

Arthur ist seit über 25 Jahren bei Parasoft im Bereich Software-Sicherheit und Testautomatisierung tätig. Er hilft bei der Erforschung neuer Methoden und Techniken (einschließlich 5 Patente) und hilft Kunden dabei, ihre Software-Praktiken zu verbessern.

Erhalten Sie die neuesten Nachrichten und Ressourcen zum Testen von Software sofort.