Testen, schwieriger als es scheint

15. Januar 2013Felix Müller

Testen ist wichtig. Genauer: Automatisierte Tests sind wichtig! Das ist mittlerweile in der IT-Branche angekommen. Allerdings gibt es große Unterschiede in der Art und Weise, wie, was und womit getestet wird. Dabei gibt es verschiedene Testarten, die unterschiedliche Ziele verfolgen. Wenn in Projekten Probleme auftauchen, heißt es oft: “aber wir haben doch Tests geschrieben” oder “siehst du, die Tests haben uns auch nicht geholfen”. Hierbei wird meistens übersehen, dass es nicht “die Tests” gibt und Unit Tests bei weitem nicht ausreichen. Daher möchte ich in diesem Beitrag auf die verschiedenen Testarten eingehen und erläutern wie diese in einem Softwareprojekt verwendet werden sollten.

Unit Tests testen die Funktionalität einzelner Klassen, isoliert vom Restsystem. Sie werden von Entwicklern für Entwickler implementiert und stellen die kleinste Einheit einer Gesamt-Testsuite im Projekt dar. Bei Unit Tests gilt das so genannte F.I.R.S.T.-Prinzip als Prämisse:

  • Fast: Es muss möglich sein, hunderte oder gar tausende Unit Tests innerhalb einer Sekunde auszuführen.
  • Isolated: Die Unit Tests müssen unabhängig (isoliert) vom Restsystem und der Umgebung (wie z.B. dem Dateisystem) funktionieren.
  • Reliable: Unit Tests müssen wiederholbar in jedweder Reihenfolge ausführbar sein und dabei verlässlich die selben Ergebnisse erzeugen.
  • Self-validating: Schlägt ein Unit Test fehl, muss anhand der Fehlermeldung sofort klar sein, woran der Fehlschlag liegt.
  • Timely: Unit Tests müssen vor dem Produktionscode geschrieben werden, Test-First-Ansatz genannt.

Integrationstests verifizieren das korrekte Zusammenspiel mehrerer Komponenten. Üblicherweise sind einfache Integrationstests in Projekten mit RDBMS sehr einfach zu implementieren, indem eine In-Memory-Datenbank verwendet wird. In komplexeren Projekten mit mehreren Drittsystemen und unterschiedlichen Speicherlösungen kann es eine große Herausforderung sein, alle Komponenten in verschiedenen Konstellationen zueinander zu testen. Je komplexer ein System ist, desto mehr lohnen sich viele Integrationstests für die unterschiedlichen Schnittstellen. Vor allem Fehlersituationen können damit sehr einfach simuliert werden.

Functional Tests sind sehr wichtig in Projekten, da mit ihnen die Funktionen für den Endnutzer getestet werden. Ein Projekt kann intern noch so ausführlich mit Unit Tests und Integrationstests getestet sein; wenn die Funktionalität nicht dem Erwartungswert entspricht, gilt es als Misserfolg. Um das zu verhindern, testen Functional Tests eine Anwendung im besten Fall durch die Endnutzer-Schnittstelle. Das ist z.B. bei Web-Anwendungen der Browser. Dafür kann beispielsweise Selenium (http://seleniumhq.org) verwendet werden.

Smoke Tests kommen zum Einsatz, wenn Build Pipelines verwendet werden oder während des Continuous Integration Builds auf Systeme deployed wird. Smoke Tests sind eine Gruppe von Tests, die verwendet werden, um sicherzustellen, dass nach einem Deployment auf ein System (z.B. ein Staging System) alles ordnungsgemäß funktioniert. Bei einer typischen B2B-Web-Anwendung wird hierbei z.B. getestet, ob die Hauptseite der Web-Anwendung geladen werden kann, ob die Anwendung die Datenbank erreichen kann und etwaige Message Broker korrekt konfiguriert sind. Ist dies nicht der Fall, ist das Ausführen weiterer Tests nicht mehr sinnvoll und der Build kann sofort abgebrochen werden.

Akzeptanztests sind meiner Meinung nach die wichtigsten Tests im Projekt. Es ist allerdings relativ schwer, diese in guter Qualität zu erstellen. Akzeptanztests machen Akzeptanzkriterien des Kunden für einzelne Funktionen automatisiert ausführbar. Damit bekommt man so genannte ausführbare Anforderungen. Diese Tests sollten daher nicht vom Entwickler erstellt werden, sondern vom Requirements Engineer in enger Zusammenarbeit mit dem Kunden. Sie sind zudem ein gutes Kommunikationsmittel, um die Anforderungen des Kunden zu formalisieren und zu dokumentieren. Tools dafür sind z.B.: JBehave (http://jbehave.org) und Cucumber (http://cukes.info).

Manuelle Tests sind die wohl häufigste Form des Testens – leider. Jedem sollte klar sein, dass manuelles Testen nicht skaliert und ein tiefes schwarzes Loch ist, das mit steigender Projektkomplexität immer mehr Aufwand verschlingt. Allerdings gibt es eine Rechtfertigung für manuelles Testen: exploratives manuelles Testen. Menschliche Nutzer finden Fehler, die ein automatisierter Test nicht identifizieren kann. Daher ist das explorative Testen eine legitime und notwendige Art des Testens. Wichtig: Dafür sollte kein detaillierter Testplan verwendet werden.

Hier nicht angesprochene, aber nicht weniger relevante Testarten sind Performance Tests und User Experience Tests.

Versuchen Sie in Ihren Projekten alle Testarten sinnvoll unterzubringen. Das Ziel ist, ein sicheres Netz an Tests zu erstellen, das schnelle Änderungen ermöglicht und Fluktuationen der Projektmitarbeiter kompensieren kann.

Weitere Gedanken, Hinweise und Tipps finden Sie in den Vortragsfolien, die diesem Beitrag zugrunde liegen: https://github.com/fmueller/testingtechtalk

Ich hoffe, ich konnte Ihnen ein paar Anregungen für Ihre nächsten Projekte geben und freue mich auf Ihre Fragen und weitere Anregungen.

Felix Müller Felix Müller ist als Software Engineer bei adesso tätig und beschäftigt sich mit der Entwicklung von Web-Anwendungen im Java-Umfeld und mit dem firmeninternen Build Management.
Artikel bewerten:
1 Star2 Stars3 Stars4 Stars5 Stars
Loading...

Kommentar hinzufügen:

Ihr Kommentar: