Fünf Tipps für besseren Testcode

5 Tipps für besseren Testcode Blogpost

Good Practices

In diesem Blogpost zeige ich fünf Good Practices auf, um den eigenen Testcode zu verbessern.
Aber wieso nur „Good Practices“?
Code und Codestyles ändern sich ständig, was heute als richtig anerkannt wird könnte morgen schon wieder falsch sein. Aus diesem Grund möchte ich hier nicht von „Best Practices“ sprechen. Möglicherweise können in der Zukunft neue Erkenntnisse aufkommen, die eine andere Schlussfolgerung zulassen.
Die nachfolgenden Tipps sind in keiner wertenden Reihenfolge angeordnet.

1. Vermeide IF/ELSE im Testcode

Testcode sollte immer gleich ausgeführt werden, das heisst gleiche Anfangsbedingungen und gleiche Endbedigungen. If/Else Blöcke erhöhen die Komplexität und erschweren unnötig das Nachvollziehen der ausgeführten Schritte.
Ist If/Else nötig, weil beispielsweise auf Änderungen am Ausgangszustand der Testumgebung (System under Test oder kurz: SUT) reagiert werden muss, empfiehlt es sich (falls möglich) die Testdaten bzw. Testumgebung anzupassen. Gleiches gillt auch für Switch-Anweisungen. Diese sollten ebenfalls so gut es geht vermieden werden.

2. Clean Code

Wie auch bei der Programmierung vom eigentlichen System, sollten die gleichen Clean Code Prinzipien auch beim Testcode angewendet werden. Das Thema Readability und Maintainability stehen hier im Vordergrund. Erreicht wird dies beispielsweise durch Code auslagern in Unterfunktionen. Grundsätzlich sollten die gleichen Qualitätsanforderungen wie beim Produktionscode eingehalten werden.

3. Vermeidung unnötiger Kommentare

Kommentare sind ein Streitthema für sich. Im Testcode sollten sie allerdings sparsam eingesetzt werden. Kommentare veralten und müssen immer gepflegt werden, dies wird des öfteren bei Änderungen vom Code übersehen. Statt Blöcke zu kommentieren empfiehlt es sich diese Codeblöcke in Unterfunktionen mit sprechendem Namen auszulagern. Somit wird der Kommentar überflüssig und veraltet nicht.
Beispiel:

//...
//ReadCSVFile
BufferedReader br = null;
int ignoreHeader = 0;
String csvSplitSymbol = ",";
String line = "";
    br = new BufferedReader(reader);
    while ( ( line = br.readLine() ) != null) {
        if (ignoreHeader > 0) {
           String[] currentLine = line.split(csvSplitSymbol);
           filecontent.add(currentLine)
        }
        ignoreHeader ++ ;
    }
//Some more Teststeps
//...

Dieser gesamte Kommentar kann eingespart werden, indem der zugehörige Codeblock in eine Unterfunktion ausgelagert wird (siehe bereits erwähnt Clean Code weiter oben).

//...
ArrayList<String> fileContent= ReadCSVFile(filename);
//Some more Teststeps
//...

Natürlich haben Kommentare ihre Daseinsbereichtigung um zum Beispiel Metainformationen über die TestKlassen zu liefern, dennoch sollten sie sparsam eingesetzt werden, um unnötige Wartung zu vermeiden.

4. Das zusammen, was zusammen gehört

Frei nach dem Motto „Das zusammen, was zusammen gehört“ ist es sinnvoll, Tests die sich auf die gleiche Funktion oder das gleiche Modul beziehen auch zu gruppieren. Dies bezieht sich nicht nur auf die gleiche Klasse, sondern auch auf das ausführen durch Testtools wie zum Beispiel TestNG. In TestNG lassen sich gleichartige Tests über eine settings.xml Datei zusammenfassen. Dadurch können Suits erstellt werden. Dieses Vorgehen macht es auch einfacher Gruppen für bestimmte Testläufe auszuschließen. Oder aber Test-Gruppen nur bei bestimmten Testläufen (beispielsweise beim Einspielen einer Fehlerbehebung) auszuführen.
Beispiel einer TestNG settings.xml

<suite name="Suite">
  <parameter name="suite-param" value="suite level parameter" />
  <test thread-count="5" name="TestNG">
    <groups>
		<run>
   			<exclude name="warenkorb_voll"/>
        </run>
    </groups>
    <classes>
      <class name="de.pmoit.schulung.exercise1"/>
    </classes>
  </test>
</suite>

5. Asserts nur am Ende eines Tests und nicht zuviele pro Test

Im Allgemeinen empfiehlt es sich, Tests nach dem Trinity Prinzip oder auch AAA (Arange, Act, Assert) aufzubauen: Zuerst werden Parameter initialisiert und Testvorraussetzungen erfüllt, dann wird der Testvorgang durchgeführt und schließlich das Ergebnis verglichen.Für gewöhnlich stehen die soll-ist-vergleiche oder auch Asserts genannt, hier am Ende eines Tests. Dies ist auch sinnvoll, da alles was nach einem negativen Assert steht, nicht mehr ausgeführt wird. Mit anderen Worten, schlägt ein Assert fehl, wird alles dannach ignoriert.Daher ist es auch naheliegend, alle Asserts ans Ende zu stellen und auch nicht zu viele pro Test zu verwenden. Beispiel:

String grass="red";
String sky ="blue";
assertEquals(grass, "green");
assertEquals(sky, "blue"); 

Bei diesem einfachen Beispiel schlägt das Assert schon in der Zeile 4 fehl, dies bedeutet Zeile 5 wird nicht mehr ausgeführt. Somit erfahren wir bei einem fehlgeschlagenen Test nicht, ob ein Fehler auch weiter unten im Code besteht oder ob dannach alles in Ordnung ist.
Somit könnten mehr Fehler unerkannt bleiben und erst nach der Behebung des ursprünglichen Fehlers zum Vorschein kommen.
Alternativ können auch weitere Assert-Bibliotheken eingesetzt werden um diese Restriktion aufzuheben. Beispielweise mit AssertJ lassen sich „Softasserts“ verwenden. Somit wird es möglich, mehrere Asserts anzuwenden bei denen zum ende des Tests alle Vergleiche ausgewertet werden.
Weiterhin besteht die Wichtigkeit, nur eine zusammenhängende Sache pro Test zu vergleichen und nicht in irgendeiner Form zu mischen. Auch mit Softasserts können ungewollte Nebeneffekte auftreten.

Fazit

Diese 5 Tipps können den eigenen Testcode verbessern, es gibt mit Sicherheit noch viel mehr Dinge auf die ein besonderes Augenmerk zu legen ist, allerdings erscheinen mir diese Grundlagen als wichtig. Ein weiterer wichtiger Faktor ist ebenfalls die Absprache mit den Entwicklern. Es ist immer von Vorteil hier einen gemeinsamen Codingstiel zu finden und sich an gemeinsame Vorgaben zu halten. Nicht nur lassen sich damit Missverständnisse vermeiden und Wartbarkeit erhöhen, es trägt auch zu einem Gemeinschaftsgefühl bei, bei dem ein stetiger Austausch positiv wahrgenommen werden kann.
Mehr zum Thema Konfiguration von Gruppen mit TestNG behandle ich in meiner Cucumber Schulung.

Interne Schulungen in Cucumber & Selenium


In geschützter Umgebung lernt und festigt Ihr Team individuelles Wissen für Ihre aktuellen Anforderungen. Damit Ihr Projekt erfolgreich und wie geplant abgeschlossen wird.

Das könnte Sie auch interessieren

Testautomatisierung mit Selenium Schulung

Testautomatisierung mit Selenium Schulung Schulungsbeschreibung Die Selenium Schulung vermittelt Basiswissen und die wichtigsten Aspekte zur Testautomatisierung. Nach...

Behaviour Driven Development (BDD) mit Cucumber und Gherkin Schulung

Behaviour Driven Development (BDD) mit Cucumber Schulung Schulungsbeschreibung In dieser Schulung lernen Teilnehmer*innen den sicheren Umgang mit BDD, Cucumber und...

API Testing mit Java und WireMock

API Testing mit Java und WireMock Motivation Ein bekanntes Problem: Öffentliche APIs werden abgefragt und liefern Daten in Form von JSON oder anderen Formaten zurück....

Rolladensteuerung mit Loxone und Java

Automatische Rolladensteuerung mit Java und Loxone Motivation Loxone ist ein bekannter Anbieter für Smarthome Rolläden. Während sich über die mitgelieferte Oberfläche...

Akzeptanztests mit Gauge und Java

Akzeptanztests mit Gauge und Java 1. Einführung In diesem Blogeintrag werde ich zunächst auf Gauge eingehen, die Installation vorstellen und anschließend ein Beispiel...

Erinnerungsassistent für Medikamente mit Sprachausgabe

Erinnerungsassistent für Medikamenteinnahme mit Sprachausgabe Motivation Bevor Corona began, besuchten Ich und meine Familie meine Großeltern regelmäßig. Dabei...

Devops mit Cucumber, Jira und Xray

Devops mit Cucumber, Jira und Xray "Hat auf meiner Maschine funktioniert, ist jetzt Operating Problem“ Diese oder vergleichbare Aussagen sind nicht neu und...

Unit Tests mit AI – Machinet Testfallerstellung

Unit Tests mit AI - Machinet Testfallerstellung Werden Tester bald durch KIs ersetzt? Spoiler: Nein In diesem Blogbeitrag möchte ich auf ein paar Grundlagen der KI...

Apple Kalender auslesen mit Java

Apple Kalender mit Java auslesen Motivation Apple Kalender-Einträge sollen synchron auf meinem Java-Dashboard sowie auf sämtlichen anderen Geräten im Haus gepflegt...