„Ihr seid doch agil, benutzt ihr auch den Hudson?“
Das ist eine gute Frage, die man – so oder so ähnlich – immer wieder von Leuten hört, die durchaus an agilen Themen interessiert sind, sich aber noch nicht wirklich weiter damit beschäftigt haben.
Aber was ist jetzt eine gute Antwort auf diese Frage? Ein einfaches „Ja!“ entspricht zwar den Tatsachen, würde der Sache aber nicht wirklich gerecht werden. Die tool-orientierte Antwort könnte auch lauten: „Ja, wir benutzen Hudson, aber wir könnten auch Bamboo oder Cruise Control nutzen.“ Verbunden mit einer länglichen technischen Begründung, warum wir uns letzten Endes für Hudson als Werkzeug entschieden haben. Hilfreich? Vermutlich eher nicht! Also nehmen wir noch einen Anlauf für eine Antwort: „Ja, wir benutzen Hudson als einen Teil unserer Umgebung für kontinuierliche Integration (Continuous Integration). Dieses wird komplementiert durch ein passendes SCM-Konzept und automatisierte Tests.“ Soweit so gut, aber zu kontinuierlicher Integration gibt es doch noch eine Menge mehr zu sagen und damit sind wir am eigentlichen Start dieser kleinen Artikelserie über Continuous Integration.
Kontinuierliche Integration – Was, Wie und Warum?
Was steckt hinter dem Begriff der kontinuierlichen Integration? Ich könnte jetzt hier natürlich Wikipedia zitieren, aber da kann jeder nach Bedarf selber nachlesen. Und es soll ja in diesem Überblick auch noch nicht zu sehr in die Tiefe gehen, das kommt dann später. Also:
Bei kontinuierlicher Integration werfen alle Entwickler allen Programmcode (mehrmals) täglich zusammen. Durch Kompilation auf einem unabhängigen Server – z.B. mit Hilfe von besagtem Hudson – wird garantiert, dass alle Teile zusammenpassen. Automatische Tests stellen sicher, dass der gesamte Programmcode wie erwartet zusammen funktioniert. Dieser gesamte Prozess läuft mehrmals täglich durch.
Das hört sich sicherlich einfacher an, als es ist. Aber bevor wir hier mehr ins Detail und die damit verbundenen Probleme – oder besser Herausforderungen 😉 – gehen, nehmen wir uns erst noch die Frage nach dem „Warum?“ vor. Warum sollte man kontinuierliche Integration in seinen Projekten und Produkten einführen? Für agile Projekte stellt sich diese Frage nicht wirklich. Ohne kontinuierliche Integration sind die kurzen Demo- und Produktzyklen überhaupt nicht durchführbar. Hierbei sind insbesondere automatisierte Tests das Rückgrat des Entwicklungsprozesses. Das Ziel dahinter ist zu jedem Zeitpunkt ein funktionierendes (Software-)Produkt ausliefern – oder zumindest demonstrieren – zu können. Als weiterer positiver Effekt werden (Integrations-)Probleme sehr früh im Projekt sichtbar und sind damit im Allgemeinen noch einfacher und damit kostengünstiger zu lösen.
Damit kommen wir wieder zu einer Frage: „Kann man kontinuierliche Integration auch in klassischen Projekten (Stichwort „Wasserfall“) verwenden?“ Die Antwort lautet denke ich jein. Testautomatisierung ist sicherlich auch in klassischen Projekten eine große Hilfe, denn auch hier kann der (manuelle) Testaufwand sonst irgendwann aus dem Runder laufen. Sein volles Potential entwickelt die kontinuierliche Integration aber erst zusammen mit agilen Entwicklungsmethoden, die dann auch zu sehr kurzen Entwicklungszyklen führen.
Was bleibt ist die Frage nach dem „Wie?“ Diese Frage bedarf einer umfangreicheren Antwort und wird daher im nächsten Abschnitt näher beleuchtet.
Aufbau einer Umgebung für kontinuierliche Integration
Eine Umgebung für kontinuierliche Integration kann beliebig komplex werden, abhängig von verschiedenen Faktoren wie dem Projektumfang, der Größe des Teams und auch dem Anspruch an das System.
Einschub „Gebrochene Builds“: Es ist unmöglich über Continuous Integration zu sprechen, ohne zu klären was wir unter einem Gebrochenen Build oder auch Broken Build verstehen. Unter einem Build wird bei kontinuierlicher Integration der gesamte Vorgang verstanden Programmcode zu integrieren, kompilieren und die automatischen Tests auf der neuen Version laufen zu lassen. Schlägt einer dieser Teile fehl spricht man von einem Gebrochenen Build oder sagt auch Das Build ist rot im Gegensatz zu Grünen Builds wenn alles funktioniert hat. Ein rotes Build wirkt wie ein Stoppschild. Es bedeutet es gibt aktuell keine funktionierende Software und im Prinzip darf niemand neuen Programmcode mehr freigeben, bis das Problem behoben ist und das Build wieder grün ist. Wie man genau mit gebrochenen Builds umgeht ist sicherlich von Team zu Team unterschiedlich, aber es ist Fakt, dass man keine kontinuierliche Integration anwendet, wenn man sich nicht um gebrochene Builds kümmert. Und wie kann der nächste Entwickler seine Änderungen Testen, wenn der offizielle Stand ohnehin nicht funktioniert?
Das folgende Diagramm gibt einen Überblick über ein einfaches – aber vollständiges – CI-Environment. Im Rahmen dieser Artikelserie soll diese Umgebung komplett aufgebaut werden. Doch dazu mehr weiter unten im Ausblick.
Mit ein wenig Erfahrung kann man durchaus ein potentielles Problem an obigem Setup erkennen. Es liegt eine Menge Verantwortung bei jedem einzelnen Entwickler sicherzustellen, dass der Build nicht gebrochen wird. D.h. idealerweise müssten Tests – auch Integration Tests – lokal bei jedem Entwickler ausführbar sein, damit diese vor einem Commit ausgeführt werden können. Dies ist jedoch für ein kleineres Team (5 – 8 Entwickler) durchaus ok.
Natürlich kann man ein CI-System beliebig weiter hoch skalieren, um damit Probleme im Build auch mit technischen Mitteln zu verhindern. Eine Möglichkeit ist ein hierarchisches System, bei dem die Entwickler nicht direkt ihren Code freigeben können, sondern dieser zunächst auf einem Pre-CI-System getestet wird. Nur Code der dort erfolgreich verifiziert wurde, wird für das finale CI-System freigegeben und dort erneut getestet.
Mit einem solchen System – welches sich noch weiter hoch skalieren lässt – kann man effektiv verhindern, dass individuelle Fehler von Entwicklern sofort auf das Build durchschlagen. Allerdings ist auch offensichtlich, dass die Kosten für Hardware und Betreuung eines solchen Systems schnell anwachsen. Mit dem richtigen Mindset lassen sich nach meiner Meinung auch mit einem einfacheren System sehr gute Ergebnisse erzielen.
Ausblick
Damit es nicht nur bei der Theorie bleibt wird der Aufbau einer CI-Umgebung in den folgenden Artikeln näher beleuchtet. Die Artikel werden hier verlinkt sobald diese verfügbar sind (so ist zumindest der Plan :-)):
- Reproduzierbare Builds mit Subversion, Maven und JUnit.
- Builds automatisch ausführen und Artefakte deployen mit Hilfe eines Hudson CI-Servers.
- Integration Tests einbinden auf Basis des Robot Frameworks.
Den ersten Schritt könnte man natürlich auch voraussetzen, aber ich denke es macht schon Sinn zunächst auf den Build-Prozess als solchen einzugehen. Danach können wir uns an die Automatisierung machen, d.h. am Ende von Schritt zwei steht bereits eine fertige und funktionierende CI-Umgebung. Diese wird dann im dritten Schritt noch einmal weiter aufgebohrt indem am Beispiel des Robot Frameworks gezeigt wird, wie sich auch Integration Tests einfach in das CI-Environment einbinden lassen.
Weitere Beiträge
von Thomas Jaspers
Dein Job bei codecentric?
Jobs
Agile Developer und Consultant (w/d/m)
Alle Standorte
Weitere Artikel in diesem Themenbereich
Entdecke spannende weiterführende Themen und lass dich von der codecentric Welt inspirieren.
Gemeinsam bessere Projekte umsetzen.
Wir helfen deinem Unternehmen.
Du stehst vor einer großen IT-Herausforderung? Wir sorgen für eine maßgeschneiderte Unterstützung. Informiere dich jetzt.
Hilf uns, noch besser zu werden.
Wir sind immer auf der Suche nach neuen Talenten. Auch für dich ist die passende Stelle dabei.
Blog-Autor*in
Thomas Jaspers
Du hast noch Fragen zu diesem Thema? Dann sprich mich einfach an.
Du hast noch Fragen zu diesem Thema? Dann sprich mich einfach an.