Suites und die Ausführung von Unit-Tests
Bevor wir an den Kern der Unit-Tests kommen, möchte ich euch im folgenden Blog mit den Suites und die Ausführung von Unit-Tests bekannt machen. Wir sehen Anhand von Beispielen wie das Framework arbeitet, eine klasse Mitmachsache.
Arbeitsweise der Suites
Die Suites dienen dazu, die Ausgabe und Ausführung der Unit-Tests zu visualisieren und zu steuern. Jedes Package hat am Anfang die beiden Annotationen %suite und %suitepath, die ihren Position in der Ausführungsstruktur definieren.
Hierbei stellt die Annotation %suite den Namen der aktuellen package-specification dar. Mit %suitepath geben wir die Position innerhalb der Baumstruktur an.
Hier ein Beispiel mit zwei Packages in einem Suitepath.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
CREATE OR REPLACE PACKAGE pkg_unittest1 IS -- %suite(Suite 1) -- %suitepath(Suitepath) --%test(Test X) procedure test_x; --%test(Test Y) procedure test_y; --%test(Test Z) procedure test_z; END pkg_unittest1; |
1 2 3 4 5 6 7 8 9 10 11 12 |
CREATE OR REPLACE PACKAGE pkg_unittest2 IS -- %suite(Suite 2) -- %suitepath(Suitepath) --%test (Test A) procedure test_a; --%test (Test B) procedure test_b; END pkg_unittest2; |
Für die Ausführung muss in den Prozeduren noch nichts drin stehen.
Wenn wir nun das Ganze mit
1 |
exec ut.run(); |
in einem SQL-Arbeitsblatt ausführen, bekommen wir folgende Ausgabe.
1 2 3 4 5 6 7 8 9 10 11 |
suitepath Suite 1 Test X [,001 sec] Test Y [,001 sec] Test Z [,001 sec] Suite 2 Test A [,001 sec] Test B [,001 sec] Finished in ,007646 seconds 5 tests, 0 failed, 0 errored, 0 disabled, 0 warning(s) |
Hier sehen wir, wie das Framework die Ausgabe mittels der Baumstruktur der Suites und Suitepaths anzeigt. Je nach Umfang der zu testenden Applikation kann die Baumstruktur entsprechend gestaltet sein um den Überblick besser behalten zu können.
Auch in unserem Beispiel wollen wir nun noch ein paar weitere Packages hinzufügen, die unsere Baumstruktur etwas umfangreicher gestalten. Unsere drei neuen Packages sehen wie folgt aus.
1 2 3 4 5 6 7 8 9 |
CREATE OR REPLACE PACKAGE PKG_BAUM1 IS -- %suite(Zweig1) -- %suitepath(Suitepath.baum.ast1) --%test(Test t1) procedure test_t1; END PKG_BAUM1; |
1 2 3 4 5 6 7 8 9 |
CREATE OR REPLACE PACKAGE PKG_BAUM2 IS -- %suite(Zweig1) -- %suitepath(Suitepath.baum.ast2) --%test(Test t2) procedure test_t2; END PKG_BAUM2; |
1 2 3 4 5 6 7 8 9 |
CREATE OR REPLACE PACKAGE PKG_BAUM3 IS -- %suite(Zweig2) -- %suitepath(Suitepath.baum.ast2) --%test(Test t3) procedure test_t3; END PKG_BAUM3; |
Und wenn wir nun wieder das Ganze mit unserem
1 |
exec ut.run(); |
im SQL-Arbeitsblatt ausführen, bekommen wir folgende Ausgabe.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
suitepath baum ast1 Zweig1 Test t1 [,002 sec] ast2 Zweig1 Test t2 [,003 sec] Zweig2 Test t3 [,003 sec] Suite 1 Test X [,001 sec] Test Y [,001 sec] Test Z [,001 sec] Suite 2 Test A [,001 sec] Test B [,001 sec] Finished in ,018359 seconds 8 tests, 0 failed, 0 errored, 0 disabled, 0 warning(s) |
Somit kann man leicht verschiedene Tests in Gruppen zusammenfassen, die später die Möglichkeit bieten, diese separat auszuführen.
Hierfür müssen wir unserem ut.run() als Parameter den Suitepath übergeben. In unserem oberen Beispiel möchte ich nun nur „ast2“ ausführen.
Der Parameter hat folgende Syntax: <schemaname>:<suitepath>
Dies bewerkstellige ich mit folgender Zeile.
1 |
exec ut.run('soc:suitepath.baum.ast2'); |
In meinem Beispiel ist der Schemaname „soc“, wird sich also zu eurem definitiv unterscheiden. Anzumerken ist, dass die Angabe des Schemanamen optional ist, die des Doppelpunkt jedoch nicht.
Und als Ergebnis bekommen wir die folgende Ausgabe.
1 2 3 4 5 6 7 8 9 10 |
suitepath baum ast2 Zweig1 Test t2 [,002 sec] Zweig2 Test t3 [,001 sec] Finished in ,005762 seconds 2 tests, 0 failed, 0 errored, 0 disabled, 0 warning(s) |
Wenn man also eine große Applikation hat, die man mit Unit-Tests bestücken will, sollte man sich vorher kurz Gedanken machen, wie man die Tests gruppieren möchte. Das erhöht die spätere Wartbarkeit und Lesbarkeit.
Ausführen von Unit-Tests
Wie bereits im vorherigen Kapitel ersichtlich, kann man die Ausführung der Unit-Tests begrenzen. Dies ist hilfreich bei der Entwicklung der Tests und beim Ausführen eines bestimmten Subset an Tests. Deshalb ist die Erstellung von einem gut strukturierten suitepath der erste Schritt für größere Applikationen.
Zum Ausführen der Unit-Test bietet das Framework die zwei Einstiegspunkte ut.run und ut_runner.run. Beide unterscheiden sich in ihrem Zweck und Verhalten.
Der meistgenutzte Einstiegspunkt wird ut.run sein, da ut_runner.run für API-Integrationen entwickelt ist und die Ausgabe der Ergebnisse nicht direkt auf den Bildschirm ausgibt.
ut.run
Die Einfachheit von ut.run ist optimal um vom Entwickler jederzeit aus SQL heraus aufgerufen zu werden. Man kann mittels einer Zeile seine Tests, oder auch nur eine Untermenge davon, ausführen.
Nachfolgend zeige ich euch ein paar Beispiele, wie man mit ut.run arbeiten kann.
Das Kürzeste zuerst. Der Aufruf ohne irgendwelche Parameter führt alle Tests im aktuell verbundenen Schema aus.
1 |
exec ut.run(); |
Hiermit führen wir alle Unit-Tests in dem spezifischen Schema SOC aus.
1 |
exec ut.run('SOC'); |
Dies führt alle Unit-Test vom Package pkg_baum1 im Schema SOC aus.
1 |
exec ut.run('soc.pkg_baum1'); |
Führt die Test-Prozedur test_t1 vom Package pkg_baum1 im Schema SOC aus. Anzumerken ist, dass bei der Ausführung dieses einen Tests, alle abhängigen Prozeduren wie %beforeall und/oder %beforeeach ausgeführt werden.
1 |
exec ut.run('soc.pkg_baum1.test_t1''); |
Wir können das Ganze auch kombinieren und mehrere Sachen mit übergeben.
Dies führt alle Tests aus pkg_baum1 im Schema SOC aus, und zusätzlich alle Tests im Schema CUST. Augenmerk auf ut_varchar2_list, welches die Übergabe als Liste ermöglicht.
1 |
exec ut.run(ut_varchar2_list('soc.pkg_baum1', 'CUST')); |
Abgesehen von der genauen Angabe von Package und Prozedur können wir auch den Suitepath mit übergeben und das Framework führt alles unterhalb des angegebene Pfades aus. Hier führen wir alles aus, was sich unter dem Suitepath suitepath.baum.ast2 befindet. Nicht zu vergessen die Angabe des Schemas, worunter er den Suitepath suchen sol.
1 |
exec ut.run('soc:suitepath.baum.ast2'); |
Reporter
Der Reporter ut_documentation_reporter ist der Standard für alle Aufrufe, weshalb man ihn nicht mit übergeben muss. Hier nutzen wir jetzt einmal den ut_xunit_reporter, welcher den Output entsprechend ändert und die Ausgabe im XUnit-Format ausgibt, was von diverser Drittsoftware verarbeitet werden kann.
1 |
exec ut.run('soc.pkg_baum1', ut_xunit_reporter()); |
Was die Reporter betrifft werde ich einen eigenen Blogeintrag zu verfassen, da diese doch recht umfangreich und mächtig sind.
SCHREIBEN SIE EINEN KOMMENTAR