Monthly Archives: August 2009

iCalender Dateiverarbeitung, Groovy!

Heute Nacht wollte ich eigentlich planen, welche Sessions ich auf der Agile 2009 besuchen möchte, die nächste Woche in Chicago stattfindet. I freue mich schon sehr auf die Konferenz und kann mich nur schwer zwischen den vielen Sessions entscheiden, weil ich so viele verpassen werde! Planung erfordert natürlich ein mindestmaß an Organisation. Auf der Homepage der Konferenz kann man sich durch das Importieren von iCalendar-Dateien die Termine der Sessions in den Kalender einpflegen. Eine großartige Idee … die leider nicht funktioniert, wenn man in einer anderen Zeitzone als Chicago lebt, oder Outlook als seinen Kalender benutzt. Meine Vermutung ist, dass eines der beiden Kriterien auf die meisten Benutzer zutrifft. Deshalb frage ich mich ernsthaft wie gut das Feature auf der Webseite getestet wurde. Naja, egal, mir hat es in den Fingern gekribbelt und ich habe einen Blick in dieSpezifikationen von iCalendar geworfen und ein kleines Groovy-Skript fabriziert, dass die bestehenden iCalendar-Dateien konvertiert.

>> Alle sessions sind konvertiert und können hier heruntergeladen werden. Fertig um in den Kalender importiert zu werden – auch nach Outlook.

Es gab mit den originären Dateien zwei Probleme. Hier ist eine Beispieldatei:

BEGIN:VCALENDAR
VERSION:2.0
PRODID:Agile2009
METHOD:PUBLISH
CALSCALE:GREGORIAN
X-WR-CALNAME:Agile2009
X-WR-CALDESC:Agile2009
BEGIN:VEVENT
UID:1220
DTSTART:20090825T140000
DTEND:20090825T173000
SUMMARY:User Stories for Agile Requirements
LOCATION:Columbus IJ
URL;VALUE=URI:http://agile2009.agilealliance.org/node/1220
DTSTAMP:20090209T022940Z
LAST-UPDATED:20090723T173948Z
END:VEVENT
END:VCALENDAR

Zeitzonen

Die Start- und Endzeit beinhalten keine Information über die Zeitzone, also wird die lokale Zeit angenommen. iCalender spezifiziert, dass die Zeit UTC ist, wenn ein “Z” angehangen wird. Die Transformation ist also sehr einfach: fünf Stunden draufzählen um von Chicago zu UTC zukommen, und ein “Z” anhängen.

Outlook

Das zweite Problem wird offenbar, wenn man versucht mehr als eine Session in Outlook zu importieren. Beim ersten Mal erstellt Outlook automatisch einen neuen Kalender “Agile2009″. Cool. Bei der zweiten Session landet diese aber wieder in einem neuen Kalender “Agile2009 (1)”. Extrem uncool. Um das zu beheben, müssen die beiden Properties X-WR-CALNAME und X-WR-CALDESC entfernt werden. Dies scheint leider ein bekanntes Problem mit Outlook zu sein. Zum Glück lässt sich das ebenfalls einfach beheben.

Groovy

Um die Konvertierung zu automatisieren, habe ich ein kleines Groovy-Skript geschrieben, welches sich erst alle gültigen Session-IDs besorgt, dann die iCalendar-Dateien herunterlädt und die beiden Fehler behebt, und mir auch noch den Text ausgibt, den ich in unser WordPress kopieren muss. Das Skript kann mit Sicherheit noch verbessert werden, aber es tut erstmal seinen Job. Was ich wirklich liebe an Groovy, ist die Möglichkeit Strings wie ein Array zu zerschneiden, und dabei mit negativen Indexen auch von hinten zählen zu können, sowie die Möglichkeiten durch das regex-Handling, das macht Aufgaben wie diese um ein Vielfaches einfacher :)

public class ConvertCalendar{
 
private static final String VCAL_TIME_FMT = "yyyyMMdd'T'HHmmss";
 
public static void main(def args){
// use the smartphone page to get all valid session numbers
// http://agile2009.pairwith.us/sessions
InputStream sessionStream = new URL("http://agile2009.pairwith.us/sessions").openConnection().inputStream
 
String sessions = org.apache.commons.io.IOUtils.toString(sessionStream);
 
List calList = new ArrayList();
 
// href="/sessions/5107"
sessions.eachMatch(/href="\/sessions\/\d{1,4}"/) {
	InputStream calendarStream = new URL("http://agile2009.agilealliance.org/session_ical/" + it[16 .. -2]).openConnection().inputStream
	String calendar = org.apache.commons.io.IOUtils.toString(calendarStream);
 
	File calendarFile = new File("./cals/temp - calendar.ics");
	def calendarFileWriter = new FileWriter(calendarFile)
	def calendarFileName = "";
	calendar.eachLine {
		def vCalLine = it;
		if (vCalLine ==~ /^X-WR-CALNAME:.*/ || vCalLine ==~ /^X-WR-CALDESC:.*/) {
			// ignore that line
		} else if (vCalLine ==~ /^DTSTART:.*/ ) {
			def origDate = Date.parse(VCAL_TIME_FMT, vCalLine[-15..-1])
			vCalLine = vCalLine[0..-16] + DateUtils.addHours(origDate,5).format(VCAL_TIME_FMT) + "Z";
			calendarFileWriter.write("${vCalLine}\n")
			calendarFileName = origDate.format("yyyy-MM-dd'T'HHmm");
		} else if (vCalLine ==~ /^DTEND:.*/) {
			def origDate = Date.parse(VCAL_TIME_FMT, vCalLine[-15..-1])
			vCalLine = vCalLine[0..-16] + DateUtils.addHours(origDate,5).format(VCAL_TIME_FMT) + "Z";
			calendarFileWriter.write("${vCalLine}\n")
		} else if (vCalLine ==~ /^SUMMARY:.*/) {
			calendarFileName = calendarFileName + " " + vCalLine[8..-1].replaceAll("[^\\w\\s]", "")
			println "Processing " + calendarFileName
			calendarFileWriter.write("${vCalLine}\n")
		} else {
			calendarFileWriter.write("${vCalLine}\n")
		}
	}
	calendarFileWriter.close();
	calendarFile.renameTo(new File("./cals/"+calendarFileName+".ics"))
 
	calList.add(calendarFileName+".ics")
	calendarStream.close();
}
 
println "Text to paste into Wordpress after uploading: "
println "<ul>"
Collections.sort(calList)
calList.each {
	println "<li><a href="\">${it}</a></li>"
}
println "</ul>"
 
}}
Andreas Ebbert-Karroum

 

JSP Tag Pooling Memory Leaks

JSP Custom Tags waren früher verbreitet im Einsatz. Obwohl man sie heute nurnoch vereinzelnd schreibt, findet sich ein spezielles Problem in fast jedem Projekt in dem JSP Custom Tags eingesetzt werden.
Da in Produktion der eingesetzte Web Container die benutzten Tags poolen wird, muss man beim Schreiben von JSP Custom Tags den Lebenszyklus (lifecycle) berücksichtige. Das Tagpooling ist von der Spezifikation erlaubt und sogar empfohlen, verursacht aber Probleme wenn man daran nicht denkt. Speichert man große Objekte in Tags, verursacht man ein Memory Leak welches den Server abstürzen lässt (oder es passiert nichts schlimmes, für den Fall daß der Pool oder das Objekt klein genug ist). In der Entwicklungsumgebung fällt dies auch oft nicht auf.
(weiterlesen …)

Fabian Lange

 

InputStream nach String konvertieren

Leider bringt die Google Suche nach “Convert InputStream to String” immernoch Ratschläge wie StringBuffer, byte[] oder sonstwas. Wenn man sich den Wildwuchs dort ansieht bekommt man graue Haare. Daher in der Hoffnung, daß es in Zukunft nur noch diese Lösung gibt dieses Posting :-)

 InputStream stream = getClass().getResourceAsStream("/classpath/resource.xml");
 String xml = org.apache.commons.io.IOUtils.toString(stream);
Fabian Lange

 

Agiles Testen – Das Herzstück agiler Softwareentwicklung

Agile Softwareentwicklung …

Agilität hat zu einem neuen Ansatz in der Softwareentwicklung geführt. Der Kunde – und damit die Kundenwünsche – stehen nun wesentlich stärker im Mittelpunkt des Entwicklungsprozesses, als dies bei eher traditionellen Methoden der Fall war – und zum Teil immer noch ist. Der Kunde soll nicht mehr am Ende eines Softwareprojekts ein Resultat “vorgesetzt” bekommen, welches dann mit großer Wahrscheinlichkeit nicht seinen ursprünglichen Vorstellungen und Wünschen entspricht. Stattdessen wird der Kunde durch die regelmäßige Auslieferung produktiver Software in den Entwicklungsprozess eingebunden. Natürlich bedeutet dies auch neue Verpflichtungen für den Kunden, wie die Teilnahme an regelmäßigen Demos. Dies ist jedoch sehr gut investierte Zeit, die an anderer Stelle auch wieder eingespart werden kann (z.B. bei der Erstellung des Pflichtenheftes). Insbesondere resultiert aus dieser intensiven Kommunikation zwischen dem Kunden und dem Entwicklungsteam ein wesentlich besseres, gemeinsames Verständnis der Fachanforderungen. Der Kunde bekommt so die Möglichkeit Änderungswünsche zu einem frühen Zeitpunkt im Projekt zu erkennen, zu formulieren und auch umgesetzt zu bekommen. Es zeigt sich in der Praxis immer wieder, dass die rein “theoretische Diskussion” von Anforderungen anhand eines klassischen Pflichtenheftes problembehaftet ist. Mit Hilfe der agilen Entwicklung werden diese Diskussionen verlagert und können zu einem guten Teil viel plastischer anhand bereits realisierter Softwarefunktionen geführt werden. Dies führt zu wesentlich besseren Resultaten, da es hilft die Erwartungen des Kunden zu erkennen und in der Software umzusetzen. Kontinuierlich messbare Größen sind hier die Qualität und die Anzahl der umgesetzten Funktionalitäten. Letzten Endes bedeutet dies auch mehr finanzielle Sicherheit für den Kunden und insgesamt mehr Kundenzufriedenheit.

… erfordert Agiles Testen

Natürlich reicht es nicht aus Kundenwünsche nur frühzeitig zu erkennen, sondern es muss auch darauf reagiert werden und geänderte Anforderungen müssen umgesetzt werden. Die Software ist also wesentlich häufigeren – und evtl. auch tiefgreifenderen – Änderungen unterworfen, als dies bei herkömmlichen Softwareprojekten der Fall ist. Hier kommt der Brückenschlag zum Agilen Testen. Bei agilen Projekten ändert sich die Software in Iterationen (oder sog. Sprints) und sie ändert sich schnell. Im Normalfall dauert ein Sprint zwei bis drei Wochen und am Ende eines Sprints soll komplett getestete Software stehen, die an den Kunden ausgeliefert und produktiv genutzt werden kann. Das Schreiben von Testplänen und deren manuelle Ausführung mit Hilfe eines Testteams ist somit keine Option mehr, da dieser Ansatz nicht Schritt halten kann mit der geforderten Geschwindigkeit und Flexibilität des agilen Entwicklungsprozesses. Die logische Konsequenz ist die Automatisierung von Tests, um diese möglichst schnell und auch möglichst häufig ausführen zu können. Denn Tests werden nun nicht nur einmal am Ende einer Iteration ausgeführt, sondern im Normalfall mehrmals täglich und von verschiedenen Entwicklern, um Änderungen zu testen bevor diese freigegeben werden (Stichwort Kontinuierliche Integration). Insbesondere sogenannte Regressiontests garantieren hierbei, dass neue Funktionen nicht bereits bestehende Funktionen beeinträchtigen. Oft werden automatisierte Tests durch so genanntes Exploratives Testen vervollständigt, bei denen im Idealfall mehrere Team-Mitglieder – oder auch andere Personen – die Software “einfach ausprobieren”. (Ganz so einfach ist es natürlich nicht, sondern das Thema exploratives Testen könnte sicherlich einen eigenen Blogbeitrag füllen.)
Mit der Qualität der automatisierten Tests steht und fällt die Qualität der Software. Dies ist vergleichbar mit der Qualität von Testplänen – und deren korrekter Ausführung – bei traditionellen Tests. Die automatisierten Tests müssen vertrauenswürdig sein und daher mit demselben hohen Qualitätsanspruch entwickelt werden, wie die eigentliche Software. Vertrauenswürdig bedeutet hierbei, dass sich ein fehlgeschlagener Test auch wirklich auf ein Problem in der getesteten Software zurückführen lässt und nicht auf einen Fehler in der Implementierung des Tests selber oder der Testumgebung. Man sollte also nicht der Illusion verfallen es würde reichen ein paar Skripte zu schreiben, aber es kann ein Anfang sein. Auch ist der initiale Aufwand für automatisierte Tests höher als bei klassischen Tests und: Dieser Aufwand kann nicht einfach an das Ende des Projekts verschoben werden. Die Entwicklung der Software und der zugehörigen automatisierten Tests muss parallel erfolgen. Wobei dies in der testgetriebenen Entwicklung noch strikter gehandhabt wird. Dort müssen die Tests vor der Software geschrieben werden.

Die Rolle des Software-Testers …

In der agilen Softwareentwicklung existiert die Rolle des klassischen Testers im Prinzip nicht mehr. Dies hat mit den geänderten Anforderungen an diese Rolle zu tun, denn Tests werden nicht länger anhand eines Testplans ausgeführt sondern programmiert. Diese Programmierung kann dabei eine vergleichbare Komplexität aufweisen wie die Implementierung der zu testenden Anwendung. Des Weiteren steht bei der agilen Entwicklung der Teamgedanke im Vordergrund. Diesem Teamgedanken läuft eine strikte Trennung in Entwicklerteams und Testteams entgegen. Im Idealfall sollte jeder Entwickler auch automatisierte Tests schreiben. In der Praxis werden sich jedoch meist einige Entwickler im Team stärker auf diesen Teilaspekt spezialisieren. Dies ist vergleichbar mit anderen Spezialisierungen in der Softwareentwicklung. Es ist jedoch unerlässlich, dass das Schreiben der automatisierten Tests in dem entsprechenden Entwicklungsteam stattfindet und nicht an eine “externe Funktion” im Unternehmen abgegeben wird. Idealerweise werden die Testfälle zusammen mit Experten aus der Fachabteilung entwickelt. Ein vielversprechender Ansatz ist hierbei das Schreiben sogenannter „Ausführbarer Spezifikationen“. Diese versuchen Spezifikation, Erklärung, Beispiel und Testbeschreibung in einem Dokument zu vereinen. Ein Ansatz den auch die im folgenden vorgestellten Tools auf die eine oder andere Art und Weise verfolgen.

… und Testing-Tools

Natürlich können automatisierte Tests und Testskripte komplett von Hand geschrieben werden. Jedoch gibt es gute Frameworks und Tools, die ein Entwicklungsteam bei der Erstellung solcher Tests unterstützen. Dabei werden Tests häufig mit Hilfe einer benutzerfreundlichen Schnittstelle verfasst und mittels Eingabeparametern und erwarteten Resultaten beschrieben. Um dies zu ermöglichen müssen jedoch zuvor die Testfunktionen implementiert werden, die in der Lage sind diese Parameter für einen Test korrekt zu verarbeiten. Das Robot Framework erwartet Testdefinitionen zum Beispiel in Form von HTML-Tabellen. Testfälle können dabei aus mehreren Schritten zusammengesetzt werden. Nach der Testausführung wird ein HTML-Report erstellt, der die Ergebnisse des Testlaufs aufbereitet. FitNesse ist ein weiteres Test-Tool, welches noch mehr Augenmerk auf das kollaborative Testen setzt. Testfälle sind daher in Form eines Wikis angelegt und können somit sehr einfach im Team bearbeitet werden. Neben den zuvor genannten frei verfügbaren Tools gibt es auch kommerzielle Tools wie zum Beispiel Twist. Dieses unterstützt ebenfalls kollaboratives Testen und bietet Unterstützung, um Testfälle umgangssprachlich zu beschreiben. Der Umfang dieser Tools rechtfertigt im Prinzip jeweils einen eigenen Artikel, zumal auch die Integration weiterer Werkzeuge – abhängig vom Anwendungsfall – betrachtet werden muss. Im Webumfeld könnte dies zum Beispiel Selenium oder Webtest für automatisierte GUI-Tests sein.

Zusammenfassung

Agiles Testen ist das Herzstück agiler Softwareentwicklung. Erst automatisierte Tests ermöglichen kontinuierliche Änderungen an der Software schnell zu testen und garantieren somit gleich bleibende Qualität. Dies ist unabdingbar für den Prozess der kontinuierlichen Integration, welcher wiederum die Grundlage für die iterative Auslieferung produktiver Software ist. Die Rolle des klassischen Softwaretesters verschiebt sich dabei in Richtung Softwareentwickler, da automatisierte Tests ausprogrammiert werden müssen. Auch sollte es in agilen Teams keine explizite Abtrennung dieser Rolle mehr geben. Unterstützt wird das automatisierte Testen durch eine Reihe frei verfügbarer und kommerzieller Tools, die für den eigenen Anwendungsfall evaluiert werden sollten. Natürlich macht es dabei Sinn Kompetenzen für ein Tool (oder einen Satz von Tools) aufzubauen und diese in mehreren Projekten zu nutzen und auszubauen. Vervollständigt werden die automatisierten Tests durch exploratives Testen. Hierbei werden die Funktionen der Software “ausprobiert” ohne dass man einem strengen vorgegebenen Testplan folgt. Es macht sicherlich Sinn, automatisierte Tests in einem Unternehmen zunächst in einem kleineren Projekt einzuführen, um die Vorgehensweisen dort zu testen und Erfahrungen zu sammeln. Hier können auch ggf. Tools evaluiert werden. Mit den gesammelten Erfahrungen lassen sich automatisierte Tests danach leichter unternehmensweit einführen. Auch wird die Qualität und die erzielte Testabdeckung ständig weiter steigen, wenn die Erfolge und Probleme der agilen Testmethoden als Teil der regelmäßigen Retrospektiven betrachtet werden.

Thomas Jaspers

 

© 2010 codecentric