Aus technischer Sicht ist es möglich, einige Pre- / Post-Push-Hooks hinzuzufügen, mit denen Unit-Tests ausgeführt werden, bevor ein bestimmtes Commit in einem Remote-Standardzweig zusammengeführt wird.
Meine Frage ist, ob es besser ist, Unit-Tests in der Build-Pipeline zu belassen (wodurch gebrochene Commits für das Repo eingeführt werden), oder ob es besser ist, "schlechte" Commits nicht zuzulassen.
Mir ist klar, dass ich mit diesen beiden Optionen nicht eingeschränkt bin. Zum Beispiel kann ich zulassen, dass alle Commits verzweigt und getestet werden, bevor Merge Commit auf Repo gesetzt wird. Aber wenn Sie genau zwischen diesen beiden Lösungen wählen müssen, welche werden Sie wählen und aus welchen Gründen genau?
Antworten:
Nein, aus zwei Gründen nicht:
Geschwindigkeit
Commits sollten schnell sein. Ein Commit, das beispielsweise 500 ms dauert, ist zu langsam und ermutigt Entwickler, sparsamer zu Commiten. Angesichts der Tatsache, dass Sie bei jedem Projekt, das größer als eine Hello World ist, Dutzende oder Hunderte von Tests durchführen müssen, wird es zu lange dauern, sie während des Pre-Commits auszuführen.
Bei größeren Projekten mit Tausenden von Tests, die minutenlang auf einer verteilten Architektur oder wochen- oder monatelang auf einer einzelnen Maschine ausgeführt werden, wird es natürlich noch schlimmer.
Das Schlimmste ist, dass Sie nicht viel tun können, um es schneller zu machen. Bei kleinen Python-Projekten mit beispielsweise hundert Komponententests dauert die Ausführung auf einem durchschnittlichen Server mindestens eine Sekunde, dauert jedoch häufig viel länger. Bei einer C # -Anwendung beträgt der Durchschnitt aufgrund der Kompilierungszeit vier bis fünf Sekunden.
Ab diesem Zeitpunkt können Sie entweder zusätzliche 10 000 US-Dollar für einen besseren Server zahlen, wodurch die Zeit verkürzt wird, jedoch nicht viel, oder Tests auf mehreren Servern ausführen, wodurch die Leistung nur verlangsamt wird.
Beide zahlen sich aus, wenn Sie Tausende von Tests (sowie Funktions-, System- und Integrationstests) haben, sodass sie in wenigen Minuten anstatt in Wochen ausgeführt werden können. Bei kleinen Projekten hilft dies jedoch nicht.
Stattdessen können Sie Folgendes tun:
Ermutigen Sie die Entwickler, Tests auszuführen, die sich stark auf den lokal geänderten Code beziehen, bevor Sie ein Commit ausführen. Möglicherweise können sie nicht Tausende von Komponententests durchführen, aber sie können fünf bis zehn von ihnen durchführen.
Stellen Sie sicher, dass das Auffinden und Ausführen relevanter Tests tatsächlich einfach (und schnell) ist. Visual Studio kann beispielsweise erkennen, welche Tests von Änderungen betroffen sein können, die seit der letzten Ausführung vorgenommen wurden. Andere IDEs / Plattformen / Sprachen / Frameworks verfügen möglicherweise über ähnliche Funktionen.
Halten Sie das Commit so schnell wie möglich. Das Erzwingen von Stilregeln ist in Ordnung, da dies häufig der einzige Ort ist und solche Überprüfungen oft erstaunlich schnell sind. Die statische Analyse ist in Ordnung, sobald sie schnell bleibt, was selten der Fall ist. Unit Tests durchzuführen ist nicht OK.
Führen Sie auf Ihrem Continuous Integration-Server Komponententests durch.
Stellen Sie sicher, dass Entwickler automatisch informiert werden, wenn sie den Build abgebrochen haben (oder wenn Komponententests fehlgeschlagen sind, was praktisch das gleiche ist, wenn Sie einen Compiler als Tool betrachten, das einige der möglichen Fehler überprüft, die Sie in Ihren Code einfügen können).
Zum Beispiel ist es keine Lösung, eine Webseite aufzurufen, um die letzten Builds zu überprüfen. Sie sollten automatisch informiert werden . Ein Popup anzeigen oder eine SMS senden sind zwei Beispiele dafür, wie sie informiert werden können.
Stellen Sie sicher, dass die Entwickler verstehen, dass das Unterbrechen des Builds (oder das Fehlschlagen von Regressionstests) nicht in Ordnung ist, und dass es ihre oberste Priorität ist, das Problem zu beheben, sobald dies geschieht. Es spielt keine Rolle, ob sie an einer Funktion mit hoher Priorität arbeiten, die ihr Chef für morgen ausliefern wollte: Sie haben den Build nicht bestanden, sie sollten ihn reparieren.
Sicherheit
Der Server, auf dem sich das Repository befindet, sollte aus Sicherheitsgründen keinen benutzerdefinierten Code wie Unit-Tests ausführen. Diese Gründe wurden bereits in CI-Runner auf demselben Server von GitLab erläutert ?
Wenn Sie dagegen einen Prozess auf dem Build-Server über den Pre-Commit-Hook starten möchten, werden die Commits noch langsamer.
quelle
Lassen Sie mich derjenige sein, der mit meinen Mitantwortenden nicht einverstanden ist.
Dies ist in der TFS-Welt als Gated Check-ins bekannt, und ich erwarte es anderswo. Wenn Sie versuchen, mit dem mit einem Gatter versehenen Check-in in eine Filiale einzuchecken, wird das Regalset an den Server gesendet, wodurch sichergestellt wird, dass Ihre Änderungen erstellt werden und die angegebenen (read: all) Komponententests bestanden werden. Wenn nicht, werden Sie benachrichtigt, dass Sie ein böser Affe sind, der den Build gebrochen hat. In diesem Fall werden die Änderungen in die Quellcodeverwaltung übernommen (yay!).
Gated Check-Ins sind meiner Erfahrung nach einer der wichtigsten Prozesse für erfolgreiche Unit-Tests - und damit auch für die Softwarequalität.
Warum?
Und natürlich haben Sie auch den Vorteil, dass jeder einzelne Änderungssatz "stabil" ist, wenn Sie Check-ins und eine solide Reihe von Tests durchgeführt haben. Sie sparen den ganzen Overhead (und das Fehlerpotential) von "Wann war der letzte gute Build?" - Alle Builds sind gut genug, um sich dagegen zu entwickeln.
Ja, es braucht Zeit, um die Tests zu erstellen und auszuführen. Nach meiner Erfahrung 5-10 Minuten für eine gute Größe C # App und ~ 5k Unit-Tests. Und das interessiert mich nicht. Ja, Leute sollten häufig einchecken. Sie sollten jedoch auch ihre Aufgaben häufig aktualisieren oder ihre E-Mails abrufen oder Kaffee oder Dutzende anderer Dinge besorgen, bei denen es sich um "Nicht-Code-Arbeiten" handelt, die den Job eines Software-Ingenieurs ausmachen, um diese Zeit in Anspruch zu nehmen. Das Auschecken von falschem Code ist weitaus teurer als 5-10 Minuten.
quelle
Commits sollten schnell ausgeführt werden. Wenn ich Code festschreibe, soll er auf den Server übertragen werden. Ich möchte nicht ein paar Minuten warten, während es eine Reihe von Tests durchführt. Ich bin verantwortlich für das, was ich auf den Server schiebe und brauche niemanden, der mich mit Commit Hooks babysittet.
Sobald der Server erreicht ist, sollte er sofort (oder innerhalb eines kurzen Zeitrahmens) analysiert, auf Einheit getestet und erstellt werden. Dies würde mich auf die Tatsache aufmerksam machen, dass Komponententests defekt sind oder nicht kompiliert wurden oder dass ich ein Durcheinander durch die verfügbaren statischen Analysetools verursacht habe. Je schneller dies erledigt ist (Aufbau und Analyse), desto schneller ist mein Feedback und desto schneller kann ich es reparieren (die Gedanken sind nicht vollständig aus meinem Gehirn verschwunden).
Also nein, setzen Sie keine Tests und solche in Commit-Hooks auf den Client. Wenn dies erforderlich ist, legen Sie sie in einem Post-Commit (da Sie keinen CI-Server haben) oder auf dem CI-Build-Server auf dem Server ab und benachrichtigen Sie mich bei Problemen mit dem Code. Blockieren Sie das Festschreiben jedoch nicht von vornherein.
Ich sollte auch darauf hinweisen, dass man bei einigen Interpretationen der testgetriebenen Entwicklung einen Komponententest einchecken sollte , der zuerst bricht . Dies demonstriert und dokumentiert den Fehler. Dann wäre ein späteres Einchecken der Code, der den Komponententest behebt . Das Verhindern von Eincheckvorgängen bis zum Bestehen der Komponententests würde den effektiven Wert des Eincheckens eines Komponententests verringern, der das Problem nicht dokumentiert.
Verwandte: Sollte ich Unit-Tests für bekannte Mängel haben? und Welchen Wert hat die Prüfung bei nicht bestandenen Komponententests?
quelle
Commits should run fast.
Was sind die Vorteile davon? Ich bin neugierig, weil wir derzeit mit einem Gatter versehene Checkins verwenden. Normalerweise sind meine Eincheckvorgänge etwa eine Stunde Arbeit, daher ist ein Warten von 5 Minuten keine große Sache. In der Tat habe ich festgestellt, dass es normalerweise die Zeiten sind, in denen ich in Eile bin, dass der Validierungs-Build am nützlichsten ist, um dumme Fehler (infolge von Eile) zu fangencatching silly mistakes (as a result of rushing)
genau. Rauschen im Allgemeinen ist eine schlechte Praxis in der Softwareentwicklung. Robert C. Martin empfiehlt, Code wie eine Operation zu schreiben. Youtube.com/watch?v=p0O1VVqRSK0Grundsätzlich halte ich es für sinnvoll, zu verhindern, dass Personen Änderungen an der Hauptlinie vornehmen, die den Build beschädigen. Das heißt, für das Vornehmen von Änderungen am Hauptzweig Ihres Repositorys muss sichergestellt werden, dass alle Tests weiterhin erfolgreich sind. Das Abbrechen des Builds ist in Bezug auf die verlorene Zeit einfach zu kostspielig, als dass alle am Projekt beteiligten Ingenieure etwas anderes tun könnten.
Die spezielle Lösung von Commit-Hooks ist jedoch kein guter Plan.
quelle
Breaking the build is simply too costly in terms of lost time for all engineers on the project
Ich würde vorschlagen, eine Art Build-Benachrichtigungs-Tool zu verwenden, um zu vermeiden, dass alle Ingenieure bei jedem unterbrochenen Build Zeit verlierenNein, das hättest du nicht tun sollen, wie andere Antworten gezeigt haben.
Wenn Sie eine Codebasis haben möchten, die garantiert keine fehlgeschlagenen Tests aufweist, können Sie stattdessen auf Feature-Zweigen entwickeln und Anforderungen in den Master ziehen. Anschließend können Sie Voraussetzungen definieren, um diese Pull-Anforderungen zu akzeptieren. Der Vorteil ist, dass Sie wirklich schnell pushen können und die Tests im Hintergrund laufen.
quelle
Es ist wirklich schrecklich, auf eine erfolgreiche Erstellung und Tests für jedes Commit für den Hauptzweig warten zu müssen, da sind sich alle einig.
Es gibt aber auch andere Möglichkeiten, einen einheitlichen Hauptzweig zu erreichen. Hier ist ein Vorschlag, ähnlich wie bei gated Check-ins in TFS, der jedoch auf jedes Versionskontrollsystem mit Verzweigungen verallgemeinerbar ist, obwohl ich hauptsächlich Git-Begriffe verwende:
Verfügen Sie über einen Staging-Zweig, für den Sie nur Zusammenführungen zwischen Ihren Entwicklungszweigen und dem Hauptzweig durchführen können
Richten Sie einen Hook ein, der einen Build startet oder in die Warteschlange stellt und die in der Staging-Verzweigung ausgeführten Commits testet, der Committer jedoch nicht warten muss
Lassen Sie den Hauptzweig nach erfolgreicher Erstellung und erfolgreichen Tests automatisch vorwärts gehen , wenn er auf dem neuesten Stand ist
Hinweis: Führen Sie die Zusammenführung nicht automatisch in der Hauptverzweigung durch, da die getestete Zusammenführung, wenn sie aus Sicht der Hauptverzweigung nicht vorwärts zusammengeführt wird, möglicherweise fehlschlägt, wenn sie mit Commits dazwischen in der Hauptverzweigung zusammengeführt wird
Als Konsequenz:
Verbieten Sie menschlichen Commits in der Hauptniederlassung, automatisch, wenn Sie können, aber auch als Teil des offiziellen Prozesses, wenn es eine Lücke gibt oder wenn es technisch nicht machbar ist, dies durchzusetzen
Zumindest können Sie sicherstellen, dass niemand es unbeabsichtigt oder ohne Bosheit tut, sobald es eine Grundregel ist. Sie sollten es niemals versuchen.
Sie müssen wählen zwischen:
Ein einzelner Staging-Zweig, der ansonsten erfolgreiche Zusammenführungen verursacht, schlägt tatsächlich fehl, wenn eine vorherige, noch nicht erstellte und nicht getestete Zusammenführung fehlschlägt
Zumindest wissen Sie, welche Zusammenführung fehlgeschlagen ist, und lassen sie korrigieren, aber die Zusammenführungen dazwischen sind für die Ergebnisse weiterer Builds und Tests (durch das Versionskontrollsystem) nicht trivial nachvollziehbar.
Sie können sich Dateianmerkungen (oder Schuldzuweisungen) ansehen, aber manchmal führt eine Änderung einer Datei (z. B. Konfiguration) an unerwarteten Stellen zu Fehlern. Dies ist jedoch ein eher seltenes Ereignis.
Mehrere Staging-Zweige, mit denen nicht in Konflikt stehende erfolgreiche Zusammenführungen zum Hauptzweig gelangen können
Sogar für den Fall, dass in einem anderen Staging-Zweig keine Konflikte auftreten, werden die Zusammenführungen fehlgeschlagen. Die Rückverfolgbarkeit ist ein bisschen besser, zumindest in dem Fall, dass bei einem Zusammenschluss keine Änderung aufgrund eines anderen Zusammenschlusses erwartet wurde. Aber auch dies ist selten genug, um sich nicht jeden Tag oder jede Woche Sorgen zu machen.
Um die meiste Zeit über widerspruchsfreie Zusammenführungen zu erzielen, ist es wichtig, die Staging-Zweige sinnvoll zu unterteilen, z. B. nach Team, Schicht oder Komponente / Projekt / System / Lösung (wie auch immer Sie es nennen).
Wenn der Hauptzweig zwischenzeitlich zu einer anderen Zusammenführung weitergeleitet wurde, müssen Sie die Zusammenführung erneut durchführen. Es ist zu hoffen, dass dies kein Problem bei nicht in Konflikt stehenden Zusammenführungen oder bei sehr wenigen Konflikten ist.
Im Vergleich zu gated Check-ins besteht der Vorteil darin, dass Sie die Garantie für eine funktionierende Hauptniederlassung haben, da die Hauptniederlassung nur vorwärts gehen darf und Ihre Änderungen nicht automatisch mit dem zusammengeführt werden, was dazwischen festgeschrieben wurde. Der dritte Punkt ist also der wesentliche Unterschied.
quelle
Ich bevorzuge "bestandene Komponententests", um Code einzureichen. Um dies zu erreichen, benötigen Sie jedoch einige Dinge.
Sie benötigen ein Build-Framework, das Artefakte zwischenspeichert.
Sie benötigen ein Testframework, das den Teststatus aus (erfolgreichen) Testläufen mit allen angegebenen Artefakten zwischenspeichert.
Auf diese Weise ist das Einchecken mit bestandenen Komponententests schnell (Gegenprüfung von der Quelle zu dem Artefakt, das erstellt wurde, als der Entwickler die Tests vor dem Einchecken überprüft hat), diejenigen mit fehlgeschlagenen Komponententests werden blockiert und Entwickler, die Vergessen Sie zweckmäßigerweise, die Builds vor dem Festschreiben zu überprüfen, und merken Sie sich dies beim nächsten Mal, da der Kompilierungs- und Testzyklus sehr lang ist.
quelle
Ich würde sagen, es kommt auf das Projekt und den Umfang der automatisierten Tests an, die beim "Festschreiben" ausgeführt werden.
Wenn die Tests, die Sie im Check-In-Trigger ausführen möchten, sehr schnell sind oder wenn der Entwickler-Workflow nach einem solchen Check-In ohnehin einige administrative Arbeiten erzwingt, sollte das meiner Meinung nach keine Rolle spielen und die Entwickler dazu zwingen, nur zu prüfen in Sachen, die absolut die grundlegendsten Tests durchführt. (Ich gehe davon aus, dass Sie mit einem solchen Trigger nur die grundlegendsten Tests durchführen würden.)
Und ich denke, wenn es die Geschwindigkeit / den Workflow zulässt, ist es eine gute Sache, Änderungen nicht an andere Entwickler weiterzuleiten, die die Tests nicht bestehen - und Sie wissen nur, ob sie fehlschlagen, wenn Sie sie ausführen.
Sie schreiben "commit ... to remote branch" in die Frage, was bedeuten würde, dass dies (a) nicht alle paar Minuten von einem Entwickler ausgeführt wird, sodass ein kurzes Warten möglicherweise sehr gut akzeptabel ist, und (b) danach Ein solches Festschreiben der Codeänderungen kann sich auf andere Entwickler auswirken, sodass zusätzliche Überprüfungen angebracht sein können.
Ich kann mit den anderen Antworten auf "Lassen Sie Ihre Entwickler beim Warten nicht die Daumen drehen" auf eine solche Operation übereinstimmen.
quelle
Gebrochene Commits sollte nicht auf zugelassen werden Stamm , weil Stamm ist das, was in die Produktion gehen kann. Sie müssen also sicherstellen, dass es ein Gateway gibt, das sie passieren müssen, bevor sie sich auf der Amtsleitung befinden . Unterbrochene Commits können jedoch in einem Repo völlig in Ordnung sein, solange es sich nicht auf dem Rumpf befindet.
Andererseits hat es eine Reihe von Nachteilen, dass Entwickler warten und Probleme beheben müssen, bevor Änderungen in das Repository übertragen werden.
Einige Beispiele:
quelle