Montag, 2. November 2009

Webanwendungen validieren

Die Sprachen (X)HTML, CSS und JavaScript bleiben die drei Grundelemente von Oberflächen im Internet - als Kür kommt immer öfter XML mit XSL-Stylesheets hinzu. Mit den meisten Programmiersprachen haben diese Sprachen gemeinsam, dass sie keine hochkomplexe und in der Regel teure Entwicklungsplattform (IDE) benötigen, sondern ein hundsgewöhnlicher Klartexteditor zum Entwickeln ausreicht. Zur Not geht es mit "Notepad" - aber ein bisschen mehr Komfort wünscht man sich in der Regel doch. In den meisten Programmier- und Auszeichnungssprachen ist man froh über folgende Features:

  • Freie Such-, Ersetzungs- und Extraktionsmöglichkeit mit regulären Ausdrücken
  • Farbliche Hervorhebung von Schlüsselwörtern und von Kommentaren
  • Auffindung von korrespondierenden Klammern, seien es eckige, runde oder geschweifte
  • Extraktion einer Art von Inhaltsverzeichnis - bestimmten Abschnittsmarkierungen im Dokument, um in grösseren Dokumenten den Überblick zu behalten und per Click in einen Abschnitt zu verzweigen. In HTML können dies die Heading-Tags <h1>, <h2> usw. sein, in JavaScript die einzelnen function's, in CSS die einzelnen Stilregeln.
  • Ein explizit aufrufbarer "Pretty Printer" für Spalteneinrückungen - aber auf keinen Fall ein automatischer!
  • Ein explizit aufrufbarer "Code Inspector" mit Syntaxprüfung, Hinweisen auf obsolete Sprachelemente oder kritische Codestellen.
  • Frei definierbare Tastencodezuordnungen für häufig benutzte Menüpunkte.
  • Manuell aufrufbare, frei definierbare Code-Templates, z.B. ein HTML-Skelett - aber auf keinen Fall automatische Codegenerierung!

Ich habe bis 2003 mit dem Editor TextPad gearbeitet, der einige dieser Features aufwies. Später bin ich auf UltraEdit umgestiegen - weil dies der in meiner Firma allgemein verwendete Editor ist.

Seit einiger Zeit hat UltraEdit einen angebundenen JavaScript-Prozessor, der eine flexiblere Möglichkeit als Macros bietet, wiederkehrende Vorgänge bei der Textbearbeitung zu automatisieren. Ausserdem gibt es einen Satz von bis zu zehn frei definierbaren Werkzeugen - Betriebssystemkommandos, die auf das aktuelle Dokument angewendet werden können. Über einen vordefinierten Menüpunkt lässt sich bereits ohne weiteren Einstellungsaufwand HTML Tidy aufrufen, ein nützlicher "Code Inspector" für HTML und XHTML. Er kann auch zum blossen Parsen eines XML-Dokuments verwendet werden.

Für JavaScript gibt es den Code Inspector jslint von JavaScript-Altmeister Douglas Crockford. Es war ein naheliegender Gedanke, diesen mit dem in UltraEdit eingebauten JavaScript-Prozessor ausführen zu lassen. Das ist tatsächlich einfach möglich und bietet darüberhinaus den Vorteil, dass man die Ausgabe nach eigenen Vorstellungen filtern kann, um nicht mit Meldungen geflutet zu werden, sondern nur anzuzeigen, was man selbst als wesentlich erachtet. Wer sich dafür interessiert, kann sich meine UltraEdit-Version von jslint von der Webseite des BSP-Praxisbuchs unter http://bsp.mits.ch/supplements/jslint.js herunterladen. Man muss das File nur in den Script-Ordner von UltraEdit packen und hat jslint dann über die Scriptliste zur Verfügung.

Etwas mühsamer, aber auch nicht unmöglich, war es, eine lokal lauffähige Version des W3C Standard-CSS-Validators zu erzeugen. Die Installation wird dadurch kompliziert, dass die Autoren ihr Tool nicht layerbewusst programmiert haben - es gibt keine Klasse, mit der sich der Validator auf einen textförmigen Eingabestream anwenden lässt und eine textförmige Ausgabe erzeugt -, sondern die Implementierung als Servlet mit dem Jigsaw-Server verquickt ist. Wer eine Java Runtime auf seinem Rechner hat, kann sich meinen 7 MB schweren Ordner css herunterladen, der alle zum Start des CSS-Validators leider nötigen JAR-Files enthält. Nach Herunterladen und Extrahieren muss man im Batchfile cssv.bat eventuell den Namen des Ordners anpassen und kann sich dann ein Werkzeug konfigurieren. Ich habe den Ordner css als Unterordner erster Ebene auf meinem Memory Stick und schreibe das Kommando daher in der Werkzeugkonfiguration wie folgt:
\css\cssv file:///%F %n%e

Das Batch File geht davon aus, dass der Befehl java ausgeführt werden kann. Ist dies bei Ihnen nicht der Fall, müssen Sie den zu wählenden Pfad von java.exe im Batch File voll qualifizieren, zum Beispiel durch Voranstellen der Umgebungsvariablen %JAVA_HOME%, oder, falls Sie auch diese nicht konfiguriert haben, durch Angabe des vollen Pfads zu java.exe. Auch hier können Sie mit der Java-Klasse FilterValidatorOutput.java noch steuern, wieviel Output Sie vom Validator bekommen möchten.

All diese Mühen werden dadurch belohnt, dass Ihnen der W3C-Validator für CSS-Files offline im Texteditor zur Verfügung steht. Vor dem Hochladen der Files haben Sie damit für HTML (mit Tidy), CSS (mit dem W3C-Validator) und JavaScript (mit Crockfords jslint) die Möglichkeit, Konsistenzchecks und Prüfungen auf kritische Codestellen per Click bzw. per Tastenkombination aufzurufen.

Zu diesen statischen Tests müssen nach dem Einchecken des HTML-, CSS- und JavaScript-Codes noch dynamische hinzukommen. Wie man für JavaScript automatische Tests erstellt, habe ich in diesem Blog bereits beschrieben: Mit dem leichtgewichtigen Testframework ECMA Unit kann man Unit Tests für JavaScript-Code verfassen. Es empfiehlt sich, die Testsuite aktuell zu halten und spätestens bei Freigabe der Transporte ins Q-System zu starten - je häufiger man sie startet, desto besser.

Weitere dynamische Tests betreffen natürlich die Oberfläche selbst. Man wird häufig im Handbetrieb die Applikation aufrufen und testen, ob beispielsweise der neue Button wie gewünscht funktioniert. Mit Automatisierung kommt man auch hier weiter. Dabei ist es sinnvoll, einen Testmodus ohne Geschäftslogik zu haben, mit dem jedes Bild der Applikation mit einem einfachen Click aufgerufen werden kann, wobei es mit Dummydaten versorgt und angezeigt wird. Ein solcher UI- oder Testmodus könnte in ABAP mit einem Benutzerparameter realisiert werden: Statt der "produktiven" Models arbeitet man im Testmodus mit Subklassen dieser Models, die Dummydaten zurückgeben.

Sobald dies möglich ist, kann man auch die Oberfläche als Ganzes mit automatisierten Tests absichern: Wer ein Test-Tool wie QuickTestProfessional zur Verfügung hat, kann nun Dialogschritte aufzeichnen und Erwartungen in Form von Checkpoints einbauen.

Mit Bordmitteln kann man Tests auch in einer dynamischen Sprache schreiben. Mit Perl kann man die Komponente HTML::Parser verwenden, um beispielsweise alle Hyperlinks aus einer Seite zu extrahieren oder im DOM zu navigieren - die einzelnen Testerwartungen lassen sich dann mit dem Modul Test::More festlegen.

Für XML- und XHTML-Ausgaben sind dynamische Tests sehr schön mit der Schemasprache Schematron zu formulieren. Die Sprache ist - im Gegensatz zu anderen Schemasprachen wie XSD Schema oder DTD's - nicht grammatikbasiert, sondern musterbasiert. Das macht es bequem, einzelne Testerwartungen an die Struktur des Dokuments zu prüfen: Sind die Elemente auf die erwartete Weise verschachtelt? Gibt es bestimmte Substrukturen, wenn ja, wie oft? Haben die Elemente die erwarteten Attributwerte und Textinhalte? Die Muster selbst werden in einem XML-Schematrondokument gesammelt und können mit einer geeigneten Implementierung auf die zu prüfenden XML-Dokumente angewendet werden.

Die Kombination von Code Inspektoren und dynamischen Tests hilft, den zu entwickelnden Code abzusichern und bei Änderungen auf allen Ebenen sicherzustellen, dass bestehende Funktionalitäten nicht geändert oder zerstört werden.

Keine Kommentare :