Build Server und Continuous Integration

Alles, was nicht direkt mit Python-Problemen zu tun hat. Dies ist auch der perfekte Platz für Jobangebote.
Antworten
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Nabend zusammen,

beruflich motiviert habe ich mich ein wenig mit obigen Themen befasst. Primär habe ich Recherche im .NET-Umfeld betrieben und einiges interessantes gefunden. Da ich weiß, dass hier einige - zumindest einer fällt mir da ein :-D - sich da gut auskennen, dachte ich mir, ich nutze mal die breite und fundierte Forenbasis für eine Art Erfahrungsaquise.

Ich wäre daran interessiert, wie Ihr Euch für welches System entschieden habt? Was waren die Kriterien für Built-Server A, CVS B und Testing-Framework C?

Es erscheint mir im .NET-Umfeld durchaus gängig, alles von MS gegebene erst einmal als besonders geeignet einzustufen, weil es aus "einer Hand" und "einem Guss" ist. Also könnte man "einfach" auf den Team Foundation Server setzen und hätte ein All-in one Paket, wenn ich das richtig verstanden habe. Eine solch oberflächliche Meinungsbildung missfällt mir aber... immerhin gibt es *viele* andere Lösungen!

Vor allem gibt es viele andere, teilweise interessanteren Ansätze: xUnit.net ist da so ein Beispiel. Die API und einige Ansätze gefallen mir persönlich besser als die von NUnit oder gar dem eingebauten Unittesting-Framework in .NET. Sicher relativ kleine Unterschiede, aber immerhin.

CruiseControl.NET wird auch viel erwähnt und scheint bewährt zu sein. Dazu gibt es auch viele Ressourcen im Web - imho ein durchaus wichtiger Faktor, da die Chance auf Probleme zu stoßen, die noch keiner gelöst hat, weitaus geringer ist. TeamCity von JetBrains bekommt im Netz auch viel Lob (und stammt aus einer "Qualitätsschmiede" ;-) )...

Zu exotische Kombinationen bergen natürlich immer ein gewisses Risiko in sich hinsichtlich der Integration und Wartbarkeit des Ökosystems. Andererseits hat man evtl. die bessere Wahl, als wenn ich mich zu stark an das MS Produkt "binde"?

Ich persönlich fände aus dem Bauch heraus ja erst einmal folgende Kombi attraktiv: Mercurial, NAnt, CruiseControl.NET, xUnit.net und moq. Allerdings fehlt mir klar die Erfahrung zu beurteilen, wie aufwendig das Setup und die Wartung davon ist... ganz abgesehen von fundierten Argumenten, wieso man welche Kombi / Lösung wählen sollte.

Hui, das war jetzt ganz schön .NET lastig... wie biege ich das Thema ein wenig in Richtung Python? :-D Naja, mir sind Erfahrungen ja durchaus auch Technologie und Sprach unabhängig wichtig! Ob nun Java oder in Ansätzen auch Python sollte egal sein, wenn es um die generellen Erfahrungen von Lösungen und Strategien der Umsetzung geht :-)

Generell denke ich aus eigener Erfahrung (wie man es nicht machen sollte :-D) und der Lektüre interessanter Artikel, dass man von Beginn an bei einem großen neuen Projekt Wert auf eine solide Build-Umgebung legen sollte. Oder habe ich mich da zu sehr von Meinungen im Netz "verführen" lassen und das alles wird überschätzt?

Also, ich freue mich über Infos, Erfahrungen, Gedanken zur Thematik und natürlich auch über gute Ressourcen :-)
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
lunar

@Hyperion Statt Mercurial würde ich persönlich Git nutzen (auch wegen Github :) ), doch das ist sicherlich Geschmacksfrage. Mit Mercurial machst Du aber sicherlich nichts falsch, ebenso wie mit NAnt und CruiseControl. Beides sind Standardwerkzeuge in .NET, NAnt ist eigentlich ohne Alternative. CruiseControl ließe sich durch Jenkins ersetzen, doch dessen .NET-Unterstützung ist vergleichsweise schlecht. Für Python ist Jenkins allerdings hervorragend geeignet, insbesondere in Verbindung mit virtualenv und tox.

.NET hat kein eingebautes Unit-Testing-Framework. Ich nehme an, Du beziehst Dich auf MSTest. Das ist nicht Teil der BCL, sondern kommt von VisualStudio, mithin benötigst Du entweder TFS als CI-System, oder eine Visual-Studio-Installation auf dem Build-Server (und jedem Build-Knoten). Im Vergleich zu NUnit oder xUnit.NET ist MSTest ohnehin reichlich primitiv, der einzige Vorteile ist die Integration in Visual Studio, doch mit Addins wie TestDriven.NET lässt sich ähnlicher Komfort auch für andere Testbibliotheken erreichen. Die nächste Version von Visual Studio hat ohnehin bessere Unterstützung für Testbibliotheken von Drittanbietern.

Ob xUnit.net besser ist als NUnit, kann ich nicht beurteilen. Allerdings beziehen sich die auf der Seite von xUnit aufgezählten Unterschiede größtenteils auf ältere NUnit-Versionen, und haben keine Gültigkeit mehr für NUnit 2.6. In dieser Version ist die Assert-basierte Test-API durch eine ersetzt, die auf Constraints aufsetzt und Erwartungen an Objekte sehr knapp und präzise ausdrücken kann. Das sieht dann in etwa so aus (die Typdeklaration in der ersten Zeile dient der Verdeutlichung, in "echtem" Code würde ich da "var" nutzen):

Code: Alles auswählen

IEnumerable<MyViewModel> models = GetMyTestFixture()
var areModelsValid = Is.Unique
    & Has.No.Null
    & !Is.Empty
    & Has.All.Property("MyCoolProperty").GreaterThan(10)
    & Has.Exactly(1).Property("MyOtherProperty").EqualTo("Hello world");
Assert.That(models, areModelsValid);
Aktuelle NUnit-Versionen nutzen auch nicht mehr so viele Attribute, insbesondere nicht "ExpectedException". Stattdessen nutzt man Lambda-Ausdrücke, um Ausnahmen zu prüfen, was wiederum mit Constraints geschieht:

Code: Alles auswählen

Assert.That(() => MyMethodThatThrowsArgumentException(foo), Throws.ArgumentException.With.Property("ParamName").EqualTo("foo"));
Ich habe mir xUnit.net nie so genau angesehen, als dass ich diese Beispiele in dessen API schreiben könnte. Ich bin mit NUnit sehr zufrieden, gerade die Constraints-API finde ich sehr gelungen, da sie die Wiederverwendung gerade zu forciert. Man kann in Hilfsmethoden höchst komplexe Constraints generieren, und die in jedem Test wiederverwenden, entweder direkt in einem Assert, oder kombiniert mit zusätzlichen Constraints. Ein großer Vorteil gegenüber Methoden, die einfach nur Asserts aneinander reihen, ist dabei, dass NUnit immer alle Constraints auswertet. Sprich, der Test bricht nicht einfach bei der ersten, nicht erfüllten Erwartung ab, sondern läuft immer komplett durch, so dass man selbst bei sehr komplexen Tests immer genau weiß, welcher Teil gepasst hat, und welcher nicht. Eine derartige API würde ich mir auch in einer Testbibliothek für Python wünschen.

"moq" habe ich nie verwendet. Die API sieht zwar nett aus, jede dahingehende Überlegung würde aber vom Alter des Projekts und der letzten Veröffentlichung gestoppt. Ich nutze RhinoMocks, dass zumindest noch halbwegs aktiv ist. Die API ist ähnlich. Allerdings habe ich bis jetzt selten Mocks in Tests verwendet. Exzessiven Gebrauch von Mocking halte ich für ein deutliches Zeichen für eine zu enge Kopplung der betreffenden Klassen. An dieser Stelle sei Ninject erwähnt, eine IoC-Bibliothek für .NET, mit der man Objekte sehr gut entkoppeln und auf höherer Ebene mit wenigen Methoden-Aufrufen wieder zusammen stecken kann. Die API ist sehr einfach, die Konfiguration kommt völlig ohne XML aus, und die Auswirkungen auf den Quelltext sind gering, in normalem Quelltext zeigt sich Ninject gar nicht, wenn man es richtig nutzt.

Die Meinung, dass eine solide Build-Umgebung an Wert kaum überschätzt werden kann, teile ich. Steht ein CI-System, neigt man dazu, nach und nach den ganzen Entwicklungs-, Test- und Release-Prozess um das CI-System herum zu bauen, so dass Entwicklungsrichtlinien (i.e. Quelltext im "master" muss immer kompilieren und alle Tests bestehen) technisch durchgesetzt und Arbeitsabläufe wann immer möglich vom CI-System automatisiert werden. Letztlich schützt man damit die Qualität des Quelltexts (frei nach der Einsicht, dass Tests nur dann etwas nützen, wenn man sie auch ausführt), erreicht schnellere Release-Zyklen, und reduziert die Arbeit der Entwickler.

Es ist letztlich einfach bequem, ein CI-System zu haben. Man muss nicht immer penibel darauf achten, ja alle Tests manuell auszuführen, man kann sich einfach darauf verlassen, dass Tests immer ausgeführt werden. Man kann in seinem eigenen Branch ruhig was kaputt machen, dass CI-System beschwert sich per E-Mail, bevor richtig Schaden entsteht, weil der kaputte Quelltext im Release gelandet ist. Man braucht auch nicht vor jedem Release zig Skripte ausführen, um alle Assemblies zu kompilieren, alle Tests auszuführen, alles in einen Installer zu verpacken und auf den Deployment-Server zu kopieren, man kann einfach den letzten Build aus dem CI-System ziehen, von dem man ja dank des CI-Systems weiß, dass er alle Tests besteht, und diesen auf die Deployment-Server kopieren, oder gleich automatisch vom CI-System dorthin kopieren lassen.

Man darf zwar den Aufwand der Konfiguration nicht unterschätzen, aber es zahlt sich aus. CI-Systeme sind ja auch kein Alles-oder-Nichts-System, sondern lassen sich Schritt für Schritt in den Entwicklungsprozess integrieren.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Vielen Dank für dieses Posting. Ich konnte es jetzt nur überfliegen, aber werde es mir heute abend mal genauer angucken und vor allem Deine Erläuterungen zu NUnit genauer ansehen. Klingt ja wirklich so, als wären da einige Dinge prima weiterentwickelt worden!

Mercurial war jetzt eher so ein Schnellschuss, da Codeplex es wohl direkt unterstützt; prinzipiell fände ich Git am besten. Lässt sich das denn angenehm in das Studio integrieren?
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
lunar

@Hyperion CodePlex unterstützt auch Git. Mir persönlich gefällt CodePlex allerdings nicht. Es hat ein paar einzigartige Features, u.a. Unterstützung für TFS und ClickOnce, fällt aber ansonsten hinter Github zurück, und hat paar Einschränkungen, die mich wirklich stören. So kann man die Dokumentation beispielsweise nicht über das VCS abrufen, sondern nur auf der Seite editieren. Ich persönlich finde es auch nicht so hübsch und angenehm zu bedienen wie Github, und habe das Gefühl, dass Gtihub mehr Entwickler anzieht.

Es gibt einen Visual-Studio-VCS-Provider für Git, der die grundlegende Funktionalität gut unterstützt. Er zeigt den Dateistatus im Solution Explorer an, kann commiten, Änderungen zurücksetzen, usw. Ob kompliziertere Dinge wie Merges oder interaktive Rebases funktionieren, habe ich nie ausprobiert. Ich nutze diesen Provider eigentlich nur zur Anzeige des Dateistatus und gelegentlich zum Committen, da die VCS-Unterstützung von Visual Studio gefühlt stark auf zentralisierte VCS ausgerichtet ist. Dementsprechend fühlt sich Git in Visual Studio an wie Subversion [1]. Meist verwende ich einen dedizierten Git-Client. Für Windows gibt es deren drei: TortoiseGit, GitExtensions und Github for Windows.

TortoiseGit habe ich nie probiert, weil ich glaube, dass der Windows Explorer kein geeignetes Frontend für ein DVCS ist. Was bei Subversion gut funktioniert, ist für Git in der Regel die falsche Entscheidung. GitExtensions versucht, alle Befehle über die Oberfläche zur Verfügung zu stellen, ist allerdings hässlich und nur aufgesetzt, da die meisten Menüpunkte einfach nur das entsprechende Git-Kommando aufrufen, und dessen Ausgabe präsentieren. Wer die Konsole unter Windows partout vermeiden möchte, wird damit glücklich, ich persönlich bin schneller, wenn ich dann einfach direkt die Konsole verwende.

Deswegen nutze ich mittlerweile Github for Windows, selbst für Repos, die nicht auf Github liegen. Dessen Oberfläche ist nicht nur sehr schick, sondern leistet genau die richtige Abstraktion von der Git-Kommandozeile (i.e. in dem es beispielsweise Push und Pull zu einem Befehl "Sync" zusammen fasst, oder die Nachricht des Commits direkt in eine Zeile für die Zusammenfassung und ein Textfeld für den Körper trennt, so wie Tim Pope es empfiehlt). Damit erfüllt es für mich genau den Zweck eines GUI-Frontends: Hübsch auszusehen, und einfache, alltägliche Dinge auch einfach zu machen. Für den Rest gibt es einen Menüpunkt, der eine Powershell im Repo öffnet, in der dann alle Git-Kommandozeilenwerkzeuge zur Verfügung stehen. Diese Powershell ist so konfiguriert, dass der Git-Status im Prompt angezeigt wird. So kann ich unter Windows fast genauso schnell und bequem mit Git arbeiten, wie ich das von OS X und Linux gewohnt bin.

[1]: Das gilt leider nicht nur für Visual Studio. Ich habe noch keine IDE gefunden, die Git oder Mercurial wirklich als DVCS einbindet, und nicht lediglich als besseres Subversion.
jeremydon
User
Beiträge: 2
Registriert: Donnerstag 23. August 2012, 15:06

danke für die ergänzung! hat mir ebenfalls geholfen! :)
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

@lunar: Vielen Dank! Naja, die VS Integration mag nicht immer optimal sein - aber oftmals ist das ein "Killerkriterium", wenn man so etwas seinen Chefs schmackhaft machen will. Da kann ich mir reiner CLI kaum kommen - auch wenn ich nichts dagegen hätte ;-)

Aber eine GUI mit separater, konfigurierter Powershell für heftige Sachen klingt doch schon mal sehr gut! Danke, das werde ich mir mal angucken.

Ich habe irgend wie keine Lust, beim neuen Projekt immer noch auf SVN zu setzen. Das fühlt sich einfach "sperrig" und "träge" an, wenn man Git gewohnt ist.

Mit Codeplex habe ich noch nicht gearbeitet, sondern nur gesehen, dass viele .NET-Projekte dort ihr Zuhause haben. Daher bin ich naiv mal davon ausgegangen, dass Mercurial im .NET-Umfeld verbreiteter ist. Naja, ich muss da erst noch heimisch werden und Erfahrungen sammeln :-)

Ich muss mir einfach dringend selber mal eine Test-CI-Infrastruktur aufbauen und ein wenig damit experimentieren. Vielleicht kann ich dann den Team Foundation Server abwenden :-D
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
seishin
User
Beiträge: 87
Registriert: Montag 19. Dezember 2011, 16:42

Interessantes Thema, vielen Dank dafür!

Experimentiere just mit folgendem herum: http://www.rhonabwy.com/wp/2009/11/04/s ... th-hudson/


Beste Grüße
sei
Antworten