Abhängigkeiten in QF-Test (Grundlagen)
Sehen Sie hier, weshalb die sog. Abhängigkeiten für Ihre Arbeit mit QF-Test sinnvoll sind und wie man sie implementiert.
Material zum Video
Transkript
Einleitung
Herzlich willkommen zum Video „Abhängigkeiten – Grundlagen“.
In diesem Video werden die Grundlagen zu QF-Test Abhängigkeiten abgedeckt. Es werden die Einsatzzwecke und die Intention von Abhängigkeiten erklärt und gezeigt, wie einfache Abhängigkeiten implementiert werden.
Nicht in diesem Video behandelt werden fortgeschrittene Themen wie zum Beispiel verschachtelte Abhängigkeiten, charakteristische Variablen oder Fehlerbehandlung. Dies ist Bestandteil anderer Videos.
Für dieses Video arbeite ich in einer speziell bereitgestellten Testsuite, welche Sie auch von der QF-Test Webseite herunterladen können. Die Testsuite verwendet den von QF-Test mitgelieferten CarConfigurator in der Webversion als „system under test“.
Wenn Sie während des Videos mit mir mitarbeiten möchten, finden Sie die in diesem Video verwendete Suite im Videokommentar. Wenn Sie lieber gleich das Ergebnis dieses Tutorials sehen möchten, dann finden Sie die fertige Suite ebenso dort.
Struktur einer Testsuite ohne Abhängigkeiten
Nun öffne ich die eben erwähnte Abhängigkeiten-Testsuite.
Lassen Sie uns einen näheren Blick auf die Implementierung des ersten Testfalls werfen.
Hier ist eine auf einfache Weise implementierter Test zu sehen. Das ist der Vorbereitungsknoten, der unser „system under test“ – also den CarConfigurator – startet.
Hier sind einige Testfälle und zuletzt ein Aufräumknoten, der unser Programm wieder schließt. Ein einzelner Testfall läuft demnach so ab: Wir setzen die Änderungen in unserem Programm zurück, dann wählen wir ein Fahrzeug, ein Sondermodell und Zubehörteile aus. Schließlich wird ein Rabattwert eingestellt und der errechnete Endpreis wird überprüft.
Der Vorbereitungs- und Aufräumknoten ist mithilfe von Prozeduren gebaut. Mit einem Doppelklick auf eine dieser Prozeduren springen wir in den Prozeduren-Ordner und sehen uns einmal alle Prozeduren an, die uns in dieser Suite zur Verfügung stehen.
Im „SUT“-Package befinden sich nur Prozeduren zum Starten und Stoppen unseres CarConfigurators.
Im „CarConfig“-Package sind Prozeduren abgelegt, die wir für die Testfälle brauche. Diese sind vorerst nicht interessant für uns.
Jetzt, da Ihnen unsere Suite in etwa bekannt ist, werde ich diesen Test durchlaufen lassen, um die Funktionsweise zu demonstrieren.
QF-Test arbeitet sich jetzt durch alle Testfälle mit den unterschiedlichen Rabattstufen durch und nun ist der Testlauf abgeschlossen.
Nachteile von manueller Vorbereitung und Aufräumen
Schauen wir uns jetzt das Protokoll von diesem Testlauf an. Erst wird das SUT gestartet, dann läuft der Testfall einmal durch, danach wird unser Programm komplett geschlossen, und im nächsten Testfall wird das „system under test“ wieder neu gestartet. Das Ganze passiert jedes Mal.
Wie sie hier sehen, brauchen wir für einen kompletten Neustart auf meinem System ca. sechs Sekunden für die Vorbereitung und fast eine Sekunde für die Aufräumarbeit. Das Ganze summiert sich und das macht einen Großteil der gesamten Zeit des Testlaufs aus. Vor allem bei größeren Anwendungen wäre ein stetiges Stoppen und Starten sehr ineffizient und stellt auch nicht das reale Anwenderverhalten dar.
Eigentlich ist dieses Aufräumen in unserem Fall bei einem normalen Durchlauf eines Testfalls unnötig. Das SUT ist ja bereits gestartet und Änderungen werden in den Testfällen ohnehin zurückgesetzt. Allerdings kann ich zur Lösung des Problems auch nicht einfach den Aufräumknoten entfernen, sonst würde nach einem Testlauf die Anwendung für immer auf der Testmaschine weiterlaufen. Außerdem könnte ein Fehler im SUT in einem unbeaufsichtigten Lauf den gesamten Testlauf kompromittieren, statt nur einen einzelnen Testfall.
Hier zeigt sich der erste Nachteil dieser aktuellen Implementierung, nämlich dass Aufräumaufrufe nicht nur bei Bedarf am Ende des Testfalls stattfinden, sondern immer.
Ein weiterer Nachteil ist, dass es nicht ohne weiteres möglich ist, nur einen einzelnen Testfall zu starten. Dieser Testlauf hat zum Beispiel beim letzten Mal einen Fehler geworfen, entweder weil der Test falsch implementiert war oder ein Defekt in dem SUT vorliegt. Um nun den einzelnen Testfall wieder auszuführen, muss ich entweder wie vorhin die gesamte Testsuite ausführen, oder ich muss die Vorbedingungen manuell herstellen.
Also hier erstmal den Vorbereitungsknoten starten und dann den Testfall ausführen, den ich benötige. In diesem Beispiel natürlich noch recht einfach, aber sobald die Tests größer werden, kann das Ganze ganz schön mühsam werden.
Wir sehen also: Mit diesen Mitteln kommen wir nicht weit.
QF-Test Abhängigkeiten – Überblick
Nun kommen die QF-Test Abhängigkeiten ins Spiel. Abhängigkeiten stellen sicher, dass die Vorbedingungen für einen Testfall erfüllt sind – Vorausgesetzt natürlich, sie sind korrekt implementiert.
Dadurch können auch einzelne Testfälle ausgeführt werden, ohne vorher manuell Vorbedingungen herstellelen zu müssen. Das funktioniert auch, wenn vorher ein völlig anderer Testfall ausgeführt wurde.
Außerdem regeln Abhängigkeiten noch den Aufräumprozess und führen dabei vor allem keine unnötigen Aufräumarbeiten aus.
Zusammengefasst lässt sich sagen: Abhängigkeiten stellen einen bestimmten Zustand sicher, während Vorbereitung- und Aufräumknoten nur bestimmte Sequenzen ausführen.
Abhängigkeit implementieren
Dann legen wir mal los und bauen eine einfache Abhängigkeit. Als Grundgerüst nehme ich den Testfall von vorhin und kopiere ihn einfach direkt darunter. Natürlich sollte ich ihn jetzt anders benennen. Zum Beispiel „Tests mit Abhängigkeit“.
Jetzt füge ich einen Abhängigkeitsknoten in den Testfall ein. Dazu drücke ich entweder oben im Menü auf ‘Einfügen’ → ‘Abhängigkeiten’ → ‘Abhängigkeit’ oder nutze ‘Rechtsklick’ → ‘Knoten einfügen’. Jetzt benenne ich das Ganze noch sinnvoll.
Vorbedingung für unsere Tests ist ja, dass unser „system under test“ läuft. Also nenne ich die Abhängigkeit einfach „SUT gestartet“, also nach dem Zustand der hergestellt werden soll.
Wie bereits gesagt regelt eine Abhängigkeit ja die Vorbereitung und den Aufräumprozess, also sollte unsere Abhängigkeit einen Vorbereitungs- und einen Aufräumknoten enthalten. Hierzu kopiere ich den passenden Aufräumknoten einfach aus dem Testfall in den Abhängigkeitsknoten hinein.
Warum habe ich die Abhängigkeit jetzt auf Testfallsatz-Ebene definiert? Nun, wie Sie hier sehen können, erbt jeder Knoten standardmäßig die Abhängigkeiten des ihm übergeordneten Elternknotens. In unserem Fall erbt also jeder Testfall die Abhängigkeiten des Testfallsatzes. Darum reicht es auch die Abhängigkeit nur dort zu definieren und sie gilt automatisch für alle Testfälle.
Damit sind wir schon mit der Erstellung unserer ersten Abhängigkeit fertig.
Abhängigkeiten in Aktion
Probieren wir sie mal aus, ob sie auch das tut, was sie tun soll. Dafür beende ich jetzt zuerst unser SUT. Wie Sie sehen, ist kein Client mehr aktiv, also ist die Vorbedingung für unsere Testfälle, dass das SUT gestartet sein soll, momentan nicht erfüllt.
Wenn ich jetzt einen einzelnen Testfall in unserer alten Testsuite starten will, ist das nicht möglich. Wie wir sehen, wirft QF-Test eine Exception. Sehen wir uns diese einmal im Protokoll an. Ich springe zur Exception. Aha. Eine ClientNotConnected
-Exception. Es besteht keine Verbindung zum Client CarConfig. Logisch. Ich habe ihn ja auch vorhin geschlossen und den Vorbereitetungsknoten dazwischen nicht ausgeführt.
Implizites Ausführen der Vorbereitung
Unsere neue Abhängigkeit sollte dieses Problem jetzt lösen. Probieren wir das einfach mal aus. Und in der Tat: Der Test wird ohne Probleme ausgeführt, obwohl die Vorbedingung nicht erfüllt war.
Was genau ist passiert? Sehen wir uns dafür doch einfach wieder das Protokoll an. Wie wir sehen, hat sich QF-Test beim Start des Testfalls zuerst die Abhängigkeit angeschaut.
Interessant ist für uns erstmal das hier: die „Benötigte Abhängigkeit“. Dieser Eintrag hier bedeutet, dass unser Testfall, „Rabattstufe 0“, die Abhängigkeit „SUT gestartet“ benötigt, um ausgeführt zu werden. Also springt QF-Test zur Abhängigkeit und führt dort den Vorbereitungsknoten aus, den wir vorhin definiert haben. QF-Test startet also das SUT automatisch.
Das macht es jetzt deutlich einfacher, einzelne Testfälle auszuprobieren.
Implizites Ausführen des Aufräumens
Sehen wir uns einmal einen gesamten Durchlauf von Anfang an an. Also wieder den Client beenden und jetzt den gesamten Testfallsatz ausführen.
Was wir direkt sehen: Die Ausführung ging jetzt deutlich schneller als bei unserem alten Testfallsatz und unsere Anwendung wurde nicht wieder zwischen den einzelnen Testfällen geschlossen.
Was genau passiert ist, können wir wieder im Protokoll erkennen. Direkt zu sehen ist die Auswirkung auf die Dauer des Testfalls. Durch das Einsparen von Beenden und Starten des Programms haben wir den Lauf in etwa acht Sekunden beendet – im Vergleich zu unseren 22 Sekunden von vorhin mehr als doppelt so schnell.
Untersuchen wir wieder die Funktionsweise der Abhängigkeiten: Im ersten Testfall hat sich nichts verändert. Der Testfall benötigt „SUT gestartet“ und führt die Vorbereitung aus. Interessant ist, dass nirgendwo ein Aufräumknoten ausgeführt wird. Das erklärt auch, weshalb sich der CarConfigurator nicht zwischen den einzelnen Testfällen geschlossen und wieder geöffnet hat.
Aber warum ist das so? Um das zu verstehen, sollten wir einen genaueren Blick auf die Funktionsweise von Abhängigkeiten werfen.
Ist unser Testfall mit Abhängigkeiten implementiert, werden deren Vorbedingungen, also die Vorbereitungssequenzen, zu Beginn jedes Testfalls sichergestellt. QF-Test führt eine Liste mit, im Protokoll zu erkennen unter ‘Gespeicherte Abhängigkeit’, auf der es die aktuell gültigen Abhängigkeiten vermerkt. Zu Beginn ist diese leer.
Wenn jetzt eine Abhängigkeit ausgeführt wird, speichert QF-Test deren Namen in der Liste ab. Ab jetzt wird jedes mal, wenn ein neuer Testfall ausgeführt wird, dessen benötigte Abhängigkeit mit denen auf der Liste abgespeicherten Abhängigkeit verglichen. Stimmen die gespeicherten und die benötigten Abhängigkeiten überein, wie hier zu sehen, wird die Aufräumaktion übersprungen. Für QF-Test sieht das so aus: Dieser Testfall und der vorherige brauchen dieselben Vorbedingungen. Dadurch ist eine Aufräumaktion dazwischen unnötig. Stattdessen entscheidet QF-Test am Anfang des Testfalls, also beim Vergleichen der Abhängigkeiten, ob es den Aufräumknoten einer Abhängigkeit ausführen muss.
Design eines Vorbereitung-Knotens
Zwischen zwei Testfällen wird auf jeden Fall wieder der Vorbereitungsknoten unserer jetzigen Abhängigkeit ausgeführt. Schließlich wollen wir sicherstellen, dass unsere Vorbedingungen erfüllt sind und nicht zwischendurch verloren gegangen sind, etwa durch eine manuelle Interaktion oder einen Absturz. Deshalb ist es auch wichtig, dass der Vorbereitungsknoten einer Abhängigkeit durchdacht implementiert ist. In der Regel muss ein Vorbereitungsknoten Folgendes leisten: Er soll das SUT starten, aber dies nur tun, falls es nicht bereits läuft. Das ist in unserer Testsuite zum Glück bereits so implementiert.
Ich springe zur Demonstration einmal kurz mit „Rechtsklick“ → „Knoten in Testsuite finden“ zu der Stelle, an der unsere Vorbereitung definiert ist. Hier sehen wir einen „Warten-auf-Client-Knoten“, der überprüft, ob unser Client CarConfigurator gerade vorhanden ist. Das Ergebnis speichert der Knoten in der Variable IsSUTRunning
ab und der nachfolgende If-Knoten nimmt diese Variable und startet, je nach Ergebnis, entweder den CarConfigurator oder eben nicht.
Es ist wichtig sich zu merken, dass dieser Ablauf immer zu Beginn eines Testfalls stattfindet. Danach nehmen der Vorbereitungs- und Aufräumknoten einer Abhängigkeit keinen Einfluss mehr auf den Ablauf.
Mehrere Abhängigkeiten
Das wollen wir uns jetzt einmal in Aktion ansehen. Ich habe bereits einen Testfall vorbereitet, mit einer anderen Abhängigkeit als bisher. Dieser Testfall ist nur zur Demonstration gedacht. Eigentlich macht er nichts, außer hier unten ins Terminal zu schreiben, welchen Schritt er gerade ausführt. Der Testfall soll nur zeigen, wie QF-Test mit mehreren unterschiedlichen Abhängigkeiten umgeht.
Führen wir nun diesen Test mit einer anderen Abhängigkeit aus und betrachten das Protokoll.
Offensichtlich unterscheiden sich die Namen der Abhängigkeiten. Vorher hatten wir „SUT gestartet“ verwendet, jetzt brauchen wir „Andere Abhängigkeit“. Erst jetzt wird der Aufräumknoten der vorherigen Abhängigkeit ausgeführt. Vorher konnte QF-Test ja nicht wissen, ob ein Aufräumen sinnvoll wäre. Schließlich hätten wir ebenso gut einen weiteren Testfall mit der Abhängigkeit „SUT gestartet“ ausführen können.
Dank dieses Mechanismus können wir nun beliebige Testfälle aus beliebigen anderen Testfallsätzen ausführen, solange diese auch mit Abhängigkeiten versehen wurden. QF-Test wird intelligent vorherige Abhängigkeiten aufräumen und neue Vorbedingungen herstellen.
Abhängigkeiten Wiederverwenden
Einen letzten Punkt möchte ich in diesem Video noch ansprechen: Wie man Abhängigkeiten mehrmals verwendet.
Sie könnten die Abhängigkeit natürlich kopieren und überall wo benötigt einfügen. Wenn die Abhängigkeit jetzt aber geändert werden soll, zum Beispiel, wenn Sie eine Fehlerbehandlung einbauen wollen, wird es schnell mühsam, jede Abhängigkeit einzeln abzuändern.
Zum Glück ist es mit QF-Test möglich, Abhängigkeiten im Prozedurenbereich abzulegen.
Als Vorbereitung erstelle ich im Prozedurenbereich ein Package für meine Abhängigkeiten. Das geht über ‘Einfügen’ → ‘Prozedur Knoten’ → ‘Package’. Das Package nenne ich einfach mal „Abhängigkeiten“. Jetzt ziehe ich meine Abhängigkeit in den Prozedurenbereich und in mein vorbereitetes Package. Natürlich hätte ich die Abhängigkeiten auch von Anfang an dort erstellen können.
Jetzt kann ich in meinem Testfall einen ‘Bezug auf Abhängigkeit Knoten’ einfügen. Dafür wähle ich ihn über ‘Einfügen’ → ‘Abhängigkeiten’ → ‘Bezug auf Abhängigkeit’ aus. Jetzt kann ich den Namen der Abhängigkeit, auf den ich mich beziehe, entweder eingeben oder ich wähle ihn mit Hilfe dieser Schaltfläche aus.
Natürlich kann ich auch einfach die Abhängigkeit aus dem Prozedurenordner an die entsprechende Stelle ziehen um automatisch einen Bezug zu erstellen.
Der „Bezug auf Abhängigkeiten“-Knoten funktioniert genauso wie der Abhängigkeitsknoten. Er ist im Endeffekt eine Verknüpfung.
Das war es auch schon mit diesem Grundlagen-Video zu Abhängigkeiten. Ich hoffe, ich konnte Ihnen die Verwendung von Abhängigkeiten schmackhaft machen. In einem Folgevideo werden wir uns der Verwendung von verschachtelten Abhängigkeiten und der Exceptionbehandlung widmen.
Sollten Sie weitere Fragen zu Abhängigkeiten oder QF-Test haben, möchte ich Sie auf unsere anderen Videos, Tutorials und auf unser umfangreiches und stets aktuelles Handbuch verweisen.
Überprüfen Sie doch im nächsten Schritt Ihre eigenen QF-Test Testsuiten, ob dort schon überall Abhängigkeiten eingesetzt werden. Der Wechsel lohnt sich auf jeden Fall!