{"id":174,"date":"2016-03-17T18:19:29","date_gmt":"2016-03-17T17:19:29","guid":{"rendered":"http:\/\/blog.ulrich-schulte.net\/?p=174"},"modified":"2016-03-17T18:28:46","modified_gmt":"2016-03-17T17:28:46","slug":"utplsql-unit-testing-fuer-oracle","status":"publish","type":"post","link":"https:\/\/ulrich-schulte.net\/?p=174","title":{"rendered":"utplsql &#8211; Unit-Testing f\u00fcr Oracle"},"content":{"rendered":"<p>Unit-Testing ist in vielen Programmiersprachen und -umgebungen ein etablierter Standard zur Qualit\u00e4tssicherung in der Software-Entwicklung, nicht jedoch unter PL\/SQL.<\/p>\n<p>\u00dcber die Gr\u00fcnde daf\u00fcr kann ich nur spekulieren. Vielleicht liegt es daran, dass der Entwickler die Technik (Abfragen, schreibende Zugriffe) nur sehr schwer von der Gesch\u00e4ftslogik trennen kann.<\/p>\n<p>Letztlich gibt es m.E. keinen wirklichen Grund, Unitests unter PL\/SQL zu unterlassen.<\/p>\n<p>Im folgenden m\u00f6chte ich die Technik und Tools vorstellen und einen Working-Prototype f\u00fcr einen einfachen PL\/SQL-Unit vorstellen.<\/p>\n<p>Dazu verwende ich <a href=\"http:\/\/utplsql.sourceforge.net\" target=\"_blank\">utplsql<\/a>, welches schon seit vielen Jahren Unit-Tests unter Oracle erm\u00f6glicht. In einem ersten Schritt starte ich den Unit-Test per Shell-Script.<\/p>\n<p>In einem weiteren Schritt stelle ich ein <a href=\"https:\/\/github.com\/iwarapter\/gradle-utplsql-plugin\" target=\"_blank\">Plugin<\/a> f\u00fcr das Build-Tool <a href=\"http:\/\/www.gradle.org\" target=\"_blank\">gradle<\/a> vor, mit dem der Test angestossen wird.<\/p>\n<h1>Installation von utplsql<\/h1>\n<p>utplsql wird nach Dokumentation installiert und kann anschliessend von allen Usern der Datenbank-Instanz verwendet werden.<\/p>\n<p>Zum Test, ob utplsql richtig funktioniert, folgen wir dem Beispiel auf der utplsql-Homepage und definieren die Funktion<\/p>\n<pre>create or replace FUNCTION betwnStr (\r\n string_in IN VARCHAR2,\r\n start_in IN INTEGER,\r\n end_in IN INTEGER\r\n )\r\n RETURN VARCHAR2\r\nIS\r\nBEGIN\r\n RETURN  SUBSTR ( string_in,start_in,end_in - start_in + 1);\r\nEND;<\/pre>\n<p>Als Test-Package verwende ich ebenfalls das Beispiel von der utplsql-Seite. Das Testpackage hat den Namen ut_btwnstr und definiert einen Test:<\/p>\n<pre>create or replace PACKAGE ut_betwnstr\r\nIS\r\n PROCEDURE ut_setup;\r\n PROCEDURE ut_teardown;\r\n PROCEDURE ut_BETWNSTR;\r\nEND ut_betwnstr;<\/pre>\n<p>Der Body mit der Test-Implementierung lautet:<\/p>\n<pre>create or replace PACKAGE BODY ut_betwnstr\r\nIS\r\n PROCEDURE ut_setup IS\r\n BEGIN\r\n   NULL;\r\n END;\r\n\r\nPROCEDURE ut_teardown\r\n IS\r\n BEGIN\r\n   NULL;\r\n END;\r\n\r\nPROCEDURE ut_betwnstr IS\r\nBEGIN\r\n utAssert.eq ('Typical valid usage',\r\n    BETWNSTR(  STRING_IN =&gt; 'abcdefg',\r\n               START_IN =&gt; 3,\r\n               END_IN =&gt; 5),\r\n    'cde');\r\n END;\r\nEND;<\/pre>\n<p>Somit haben wir einen Test definiert, den wir aus sqlplus aufrufen:<\/p>\n<pre>Begin\r\n utplsql.test (\r\n     samepackage_in =&gt; false,\r\n     package_in =&gt; 'betwnstr',\r\n     prefix_in =&gt; 'UT_',\r\n     recompile_in =&gt; false);\r\nEnd;<\/pre>\n<p>Wichtig ist hierbei, dass utplsql eigentlich immer als Aufrufparameter den Namen des zu testenden Objekts fordert &#8211; also nicht den Namen des Testpackages!<\/p>\n<p>Es gibt sicher noch andere M\u00f6glichkeiten, diesen Aufruf zu formulieren, die Ausgabe ist immer:<\/p>\n<pre>SQL*Plus: Release 11.2.0.3.0 Production on Thu Mar 17 18:15:43 2016\r\nCopyright (c) 1982, 2012, Oracle.\u00a0 All rights reserved.\r\nConnected to:\r\nOracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production\r\nWith the Partitioning, OLAP, Advanced Analytics and Real Application Testing options\r\n.\r\n&gt;\u00a0 \u00a0 SSSS \u00a0 U \u00a0 U \u00a0 CCC \u00a0 \u00a0 CCC \u00a0 EEEEEEE \u00a0 SSSS \u00a0 \u00a0 SSSS\r\n&gt; \u00a0 S S\u00a0 U \u00a0 U\u00a0 C C \u00a0 C C\u00a0 E \u00a0 \u00a0 S \u00a0 S \u00a0 S\u00a0 \u00a0 S\r\n&gt;\u00a0 S \u00a0 \u00a0 U \u00a0 U C \u00a0 C C \u00a0 C E \u00a0 \u00a0 S \u00a0 \u00a0 S\r\n&gt; \u00a0 S \u00a0 \u00a0 U \u00a0 U C \u00a0 \u00a0 C \u00a0 \u00a0 E \u00a0 \u00a0 S \u00a0 \u00a0 \u00a0 S\r\n&gt;\u00a0 \u00a0 SSSS \u00a0 U \u00a0 U C \u00a0 \u00a0 C \u00a0 \u00a0 EEEE\u00a0 \u00a0 \u00a0 SSSS \u00a0 \u00a0 SSSS\r\n&gt; S\u00a0 U \u00a0 U C \u00a0 \u00a0 C \u00a0 \u00a0 E \u00a0 S \u00a0 S\r\n&gt; \u00a0 S U \u00a0 U C \u00a0 C C \u00a0 C E \u00a0 S \u00a0 \u00a0 S\r\n&gt; \u00a0 S S \u00a0 U U \u00a0 C C \u00a0 C C\u00a0 E \u00a0 \u00a0 S \u00a0 S \u00a0 S\u00a0 \u00a0 S\r\n&gt;\u00a0 \u00a0 SSSS \u00a0 \u00a0 UUU \u00a0 \u00a0 CCC \u00a0 \u00a0 CCC \u00a0 EEEEEEE \u00a0 SSSS \u00a0 \u00a0 SSSS\r\n.\r\nSUCCESS: \".betwnstr\"\r\n.\r\n&gt; Individual Test Case Results:\r\n&gt;\r\nSUCCESS - betwnstr.UT_BETWNSTR: EQ \"Typical valid usage\" Expected \"cde\" and got\r\n\"cde\"\r\n&gt;\r\n&gt; Errors recorded in utPLSQL Error Log:\r\n&gt;\r\n&gt; NONE FOUND\r\nPL\/SQL procedure successfully completed.\r\nDisconnected from Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production\r\nWith the Partitioning, OLAP, Advanced Analytics and Real Application Testing options<\/pre>\n<p>Die Testausf\u00fchrung hat geklappt, die Tests waren erfolgreich.<\/p>\n<p>Im n\u00e4chsten Artikel geht es dann um die Integration von utplsql in das Build-Tool Gradle.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Unit-Testing ist in vielen Programmiersprachen und -umgebungen ein etablierter Standard zur Qualit\u00e4tssicherung in der Software-Entwicklung, nicht jedoch unter PL\/SQL. \u00dcber die Gr\u00fcnde daf\u00fcr kann ich nur spekulieren. Vielleicht liegt es daran, dass der Entwickler die Technik (Abfragen, schreibende Zugriffe) nur sehr schwer von der Gesch\u00e4ftslogik trennen kann. Letztlich gibt es m.E. keinen wirklichen Grund, Unitests &hellip; <a href=\"https:\/\/ulrich-schulte.net\/?p=174\" class=\"more-link\"><span class=\"screen-reader-text\">utplsql &#8211; Unit-Testing f\u00fcr Oracle<\/span> weiterlesen <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2},"jetpack_post_was_ever_published":false},"categories":[5],"tags":[14,12,13],"class_list":["post-174","post","type-post","status-publish","format-standard","hentry","category-oracle","tag-grade","tag-oracle","tag-unittest"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p8NCNL-2O","jetpack-related-posts":[],"_links":{"self":[{"href":"https:\/\/ulrich-schulte.net\/index.php?rest_route=\/wp\/v2\/posts\/174","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/ulrich-schulte.net\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/ulrich-schulte.net\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/ulrich-schulte.net\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/ulrich-schulte.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=174"}],"version-history":[{"count":6,"href":"https:\/\/ulrich-schulte.net\/index.php?rest_route=\/wp\/v2\/posts\/174\/revisions"}],"predecessor-version":[{"id":182,"href":"https:\/\/ulrich-schulte.net\/index.php?rest_route=\/wp\/v2\/posts\/174\/revisions\/182"}],"wp:attachment":[{"href":"https:\/\/ulrich-schulte.net\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=174"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/ulrich-schulte.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=174"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/ulrich-schulte.net\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=174"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}