{"id":43,"date":"2011-11-23T19:01:00","date_gmt":"2011-11-23T19:01:00","guid":{"rendered":"http:\/\/euve3303.vserver.de\/stefan\/blog\/?p=44"},"modified":"2011-12-02T21:31:26","modified_gmt":"2011-12-02T20:31:26","slug":"sql-coverage-messen","status":"publish","type":"post","link":"https:\/\/cogito-ergo-blog.de\/blog\/2011\/11\/23\/sql-coverage-messen\/","title":{"rendered":"SQL Coverage messen"},"content":{"rendered":"<p>Seit langem bin ich mal wieder aktiv in der Implementierung einer Komponente, wenn auch erst mal nur ein Prototyp.<\/p>\n<p>Die Persistenz ist &#8211; nach dem neusten Trend &#8220;back to the roots&#8221; &#8211; nur noch mit dem JdbcTemplate von Spring gemacht. Da kann man wieder richtiges SQL schreiben und wei\u00df auch genau was passiert (bei Hibernate war ich mir nicht immer so ganz sicher).<\/p>\n<p>Als es dann ans Testen ging und ich mir Gedanken um die Testabdeckung machte, fiel mir auf, dass das was bei if-Anweisungen oder bedingter Zuweisung im Java-Code als &#8220;missed 2 of 4 branches&#8221; an gemeckert wurde, an vielen Stellen in den Where-Clauses der SQL-Statements genauso auftritt.<\/p>\n<p>Die Coverage in Java war also bei mancher Methode auf 100% aber das SQL-Statement lie\u00df viele Varianten von ResultSets zu je nach dem, was man f\u00fcr Testdaten verwendet und welche konkreten Parameter man bindet.<\/p>\n<p>Wie also l\u00e4\u00dft sich die SQL-Coverage messen?<br \/>\n<!--more--><\/p>\n<h2>SQL tracen<\/h2>\n<p>Zun\u00e4chst einmal ist es n\u00fctzlich die SQL-Statement mitschrieben zu lassen, die tats\u00e4chlich ausgef\u00fchrt werden inklusive der aktuell gebundenen Parameter. Hierf\u00fcr kann man Tools wie <a class=\"moz-txt-link-freetext\" href=\"http:\/\/code.google.com\/p\/log4jdbc-remix\/\">http:\/\/code.google.com\/p\/log4jdbc-remix\/<\/a> bzw. <span class=\"moz-txt-link-freetext\"><a href=\"http:\/\/code.google.com\/p\/log4jdbc\/\">http:\/\/code.google.com\/p\/log4jdbc\/<\/a> verwenden. Diese JDBC-Treiber arbeiten als Proxy und werden einfach &#8220;zwischen&#8221; die Applikation und den echten Treiber &#8220;geh\u00e4ngt&#8221;. Dadurch wird es einfach m\u00f6glich alle SQL-Statements die man bei Ablauf einer Testsuite an die Datenbank schickt mitzuschreiben.<\/span><\/p>\n<p>Aber leider weiss man damit immer noch nicht, ob man nun alle m\u00f6glichen &#8220;Zweige&#8221; aller Where-Bedingungen aller SQL-Statements durchlaufen hat.<\/p>\n<h2>SQL Rules und QAShrink<\/h2>\n<p><span class=\"moz-txt-link-freetext\">SQL Rules und QAShrink sind zwei Tool, die genau dar\u00fcber Aufschluss geben k\u00f6nnen. Sie sind in der Lage ein gegebenes SQL-Statement zu analysieren nach der &#8220;Full Predicate Coverage&#8221; Methode. Es werden also Regeln erzeugt, die alle Verzweigungen oder Varainten die ein SQL-Statement erzeugen kann, ber\u00fccksichtigt.<\/span><\/p>\n<p>Dabei werden nicht nur Where-Bedingungen in Betracht gezogen, sondern nat\u00fcrlich auch Joins oder Group By-Klauseln. SQLRules zeigt zu einen einzelnen Statement diese Rules an, so dass man sich anschauen kann, welche m\u00f6glichen &#8220;Pfade&#8221; zur Ergebnisfindung durchlaufen werden k\u00f6nnen.<\/p>\n<h2>Regeln anwenden<\/h2>\n<p><span class=\"moz-txt-link-freetext\">Im n\u00e4chsten Schritt lassen sich diese Regeln dann gegen einen Testdatenbestand anwenden \/ testen. Als Ergebnis bekommt man eine Aussage, ob die betreffende Regel verwendet wurde oder nicht, also ob dieser Pfad bei den zugrunde gelegten Daten durchlaufen wurde oder nicht. Das ist genau die SQL-Coverage die man braucht.<\/span><\/p>\n<p>Das andere Tool QAShrink kann dieses Prinzip gleich auf eine ganze Liste von SQL-Statements anwenden<span class=\"moz-txt-link-freetext\">. Es erzeugt dann Aussagen bzgl. der Coverage der SQL-Statements und der Vollst\u00e4ndigkeit bzw. der Redundanz der Testdaten.<\/span><\/p>\n<p>Auf diese Weise kann man also ziemlich schnell herausfinden, welche Testdaten \u00fcberfl\u00fcssig und welche noch zu erg\u00e4nzen sind, um &#8211; bei gegebener Liste der SQL-Statements &#8211; die SQL-Coverage m\u00f6glichst hoch zu machen.<\/p>\n<h2>Zusammenfassung<\/h2>\n<p>Das Vorgehen zum Erreichen einer m\u00f6glichst hohen SQL-Coverage l\u00e4\u00dft sich also so zusammenfassen:<\/p>\n<ol>\n<li>Mit einem JDBC-Proxy Treiber erzeugt man eine Liste von konkreten SQL-Abfragen, die von einer TestSuite mit hoher Code-Coverage erzeugt wird.<\/li>\n<li>Die Liste der SQL-Statemant f\u00fcttert man in QAShrink und l\u00e4\u00dft sie gegen den gleichen Testdatenbestand wie die TestSuite laufen.<\/li>\n<li>Anhand der Ergebnisse kann man den Testdatenbestand so lange um Datens\u00e4tze erg\u00e4nzen, bis eine optimale SQL-Coverage erreicht ist.<\/li>\n<\/ol>\n<p>Links zu den Tools:<br \/>\n<a class=\"moz-txt-link-freetext\" href=\"http:\/\/in2test.lsi.uniovi.es\/sqltools\/sqlrules\/\">http:\/\/in2test.lsi.uniovi.es\/sqltools\/sqlrules\/<\/a><br \/>\n<a class=\"moz-txt-link-freetext\" href=\"http:\/\/in2test.lsi.uniovi.es\/sqltools\/qashrink\/\">http:\/\/in2test.lsi.uniovi.es\/sqltools\/qashrink\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Seit langem bin ich mal wieder aktiv in der Implementierung einer Komponente, wenn auch erst mal nur ein Prototyp. Die Persistenz ist &#8211; nach dem neusten Trend &#8220;back to the roots&#8221; &#8211; nur noch mit dem JdbcTemplate von Spring gemacht. &hellip; <a href=\"https:\/\/cogito-ergo-blog.de\/blog\/2011\/11\/23\/sql-coverage-messen\/\">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":{"footnotes":""},"categories":[9],"tags":[],"_links":{"self":[{"href":"https:\/\/cogito-ergo-blog.de\/blog\/wp-json\/wp\/v2\/posts\/43"}],"collection":[{"href":"https:\/\/cogito-ergo-blog.de\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/cogito-ergo-blog.de\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/cogito-ergo-blog.de\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/cogito-ergo-blog.de\/blog\/wp-json\/wp\/v2\/comments?post=43"}],"version-history":[{"count":3,"href":"https:\/\/cogito-ergo-blog.de\/blog\/wp-json\/wp\/v2\/posts\/43\/revisions"}],"predecessor-version":[{"id":10046,"href":"https:\/\/cogito-ergo-blog.de\/blog\/wp-json\/wp\/v2\/posts\/43\/revisions\/10046"}],"wp:attachment":[{"href":"https:\/\/cogito-ergo-blog.de\/blog\/wp-json\/wp\/v2\/media?parent=43"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/cogito-ergo-blog.de\/blog\/wp-json\/wp\/v2\/categories?post=43"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/cogito-ergo-blog.de\/blog\/wp-json\/wp\/v2\/tags?post=43"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}