Wozu Unit-Tests auf einem CI-Server ausführen?

98

Warum sollten Sie Komponententests auf einem CI-Server durchführen?

Zu dem Zeitpunkt, an dem sich etwas für den Master engagiert, hat ein Entwickler sicherlich bereits alle Komponententests durchgeführt und alle Fehler behoben, die möglicherweise bei seinem neuen Code aufgetreten sind. Ist das nicht der Sinn von Unit-Tests? Ansonsten haben sie nur fehlerhaften Code geschrieben.

Steve
quelle
51
Unsere Entwickler dürfen sich nicht zum Master verpflichten. Sie werden in einen Feature-Zweig verschoben, der CI-Server wird dann mit dem Master zusammengeführt und führt Tests durch. Wenn sie Erfolg haben , dann werden Änderungen an Master verschmolzen. Also Code mit kaputten Tests kann nicht auf Master sein ...
Boris the Spider
2
@ BoristheSpider - sehr guter Workflow. mastersollte immer vernünftig sein und vorzugsweise automatisch bei jeder Zusammenführung in eine Staging-Umgebung für interne QS und Tests bereitgestellt werden.
Per Lundberg
130
"Zu dem Zeitpunkt, an dem sich etwas dem Master verschrieben hat, hat ein Entwickler bereits alle Komponententests durchgeführt und alle Fehler behoben, die möglicherweise bei seinem neuen Code aufgetreten sind." In welcher Fantasiewelt lebst du?
jpmc26
5
In einigen Branchen ist es nicht nur wichtig, die Tests für den Code auszuführen, sondern auch, die Tests für die Binärdateien auszuführen . Wenn Sie die Tests für die CI-Ausgabe ausführen, können Sie sicherstellen, dass das gelieferte Produkt funktioniert, da die genaue Binärdatei, die Ihr Client erhalten hat, alle Ihre Tests bestanden hat. Es klingt trivial, aber manchmal kann dies eine Auswirkung haben (eine, die ich gesehen habe, ist die Verschleierung; bei komplexen Projekten oder bei einer seltsamen Einrichtung kann es zu Problemen im verschleierten Build kommen, die es in der sauberen Version nicht gab).
Anaximander
5
"Zu dem Zeitpunkt, an dem sich etwas dem Master verschrieben hat, hat ein Entwickler bereits alle
Komponententests

Antworten:

223

Zu dem Zeitpunkt, an dem sich etwas für den Master engagiert, hat ein Entwickler sicherlich bereits alle Komponententests durchgeführt und alle Fehler behoben, die möglicherweise bei seinem neuen Code aufgetreten sind.

Oder nicht. Dafür kann es viele Gründe geben:

  • Der Entwickler hat nicht die Disziplin, das zu tun
  • Sie haben vergessen
  • Sie haben nicht alles festgeschrieben und einen unvollständigen Festschreibungssatz durchgesetzt (danke Matthieu M.
  • Sie haben nur einige Tests durchgeführt, aber nicht die gesamte Suite (danke nhgrif )
  • Sie haben vor dem Zusammenführen auf ihrem Zweig getestet (danke nhgrif * 2)

Der eigentliche Punkt ist jedoch, die Tests auf einem Computer auszuführen, der nicht der Entwicklercomputer ist. Eine, die anders konfiguriert ist.

Dies hilft dabei, Probleme zu beheben, bei denen Tests und / oder Code von etwas abhängig sind, das für eine Entwickler-Box spezifisch ist (Konfiguration, Daten, Zeitzone, Gebietsschema usw.).

Weitere gute Gründe für CI-Builds, Tests durchzuführen:

  • Testen auf anderen Plattformen als den Hauptentwicklungsplattformen, was für Entwickler schwierig sein kann. (danke TZHX )
  • Akzeptanz / Integration / Ende zu Ende / Auf dem CI-Server werden möglicherweise Tests mit langer Laufzeit ausgeführt, die normalerweise nicht auf einer Entwickler-Box ausgeführt würden. (danke Ixrec )
  • Ein Entwickler kann vor dem Push / Commit eine kleine Änderung vornehmen (dies ist eine sichere Änderung und führt die Tests daher nicht aus). (danke Ixrec * 2)
  • Die CI-Serverkonfiguration enthält normalerweise nicht alle Entwicklertools und -konfigurationen und ist daher näher am Produktionssystem
  • CI-Systeme erstellen das Projekt jedes Mal von Grund auf neu, dh Builds sind wiederholbar
  • Eine Bibliotheksänderung kann Downstream-Probleme verursachen. Ein CI-Server kann so konfiguriert werden, dass alle abhängigen Codebasen und nicht nur die Bibliothek erstellt werden
Oded
quelle
36
Andere häufige Gründe: 1) Auf dem CI-Server werden möglicherweise umfassende Integrations- / Akzeptanztests ausgeführt, die für die Entwickler zu lange dauern, um immer ausgeführt zu werden. 2) Der Entwickler hat sie ausgeführt und dann eine winzige Änderung vorgenommen, bevor er darauf drückte, dass sie mit großer Sicherheit nichts kaputt machen würden, aber wir möchten sicher sein, dass es funktioniert.
Ixrec
11
Ein Wechsel in eine Abhängigkeit führt häufig auch alle nachgelagerten Builds aus. Wenn eine Änderung, die ein Entwickler vornimmt, etwas Downstream bricht, ist dies beim Ändern einer Bibliothek (z. B. Ändern eines zugrunde liegenden Datentyps von einem SortedSet in ein HashSet (wobei nur der Vertrag von Set bereitgestellt wird) nicht leicht zu erkennen, und jemand Downstream hat an der falschen Annahme gearbeitet, dass das Set wurde sortiert). Wenn die (Downstream-) Tests nicht auf dem CI-Server ausgeführt werden, kann dieser Fehler eine Weile schwinden.
2
@ MichaelT Guter Fang. Das ist tatsächlich die Ursache für> 90% unserer CI-Ausfälle in diesen Tagen, nicht sicher, wie ich es vergessen habe ...
Ixrec
34
Wenn Sie sie in einer CI-Umgebung ausführen, müssen Sie in der Regel Ihr Projekt von Grund auf neu einrichten und sicherstellen, dass Ihr Build wiederholbar ist .
Margarciaisaia
5
Es können auch zwei Änderungen festgeschrieben werden, die separat getestet wurden, aber zusammenbrechen (z. B. eine, die eine nicht verwendete API entfernt und die andere, die sie verwendet).
Simon Richter
74

Als Entwickler, der nicht alle Integrations- und Komponententests durchführt, bevor er sich zur Quellcodeverwaltung verpflichtet, werde ich hier meine Verteidigung anbieten.

Ich müsste erstellen, testen und überprüfen, ob eine Anwendung korrekt ausgeführt wird:

  • Microsoft Windows XP und Vista mit Visual Studio 2008-Compiler.
  • Microsoft Windows 7 mit Visual Studio 2010-Compiler.
    • Oh, und das MSI baut für jeden von denen.
  • RHEL 5 und 6 mit 4.1 bzw. 4.4 (ähnlich CentOS)
    • 7 bald. Woop-de-woop.
  • Fedora Workstation mit GCC für die letzten drei aktuellen Versionen.
  • Debian (und Derivate wie Ubuntu) für die letzten drei aktuellen Versionen.
  • Mac OSX in den letzten drei aktuellen Versionen.
    • Und die Pakete (rpm, dmg, etc)

Fügen Sie Fortran (mit Intel- und GNU-Compilern), Python (und je nach Betriebssystem verschiedene Versionen) und Bash / Bat-Skriptkomponenten hinzu

Das sind also 16 Maschinen, die ich haben müsste, nur um ein paar Tests mehrmals am Tag durchzuführen. Es wäre fast eine Vollzeitbeschäftigung, nur die Infrastruktur dafür zu verwalten. Ich denke, fast jeder würde zustimmen, dass das unvernünftig ist, besonders wenn man es mit der Anzahl der Leute im Projekt multipliziert. Wir überlassen es unseren CI-Servern, die Arbeit zu erledigen.

Unit-Tests halten Sie nicht davon ab, defekten Code zu schreiben. Sie informieren Sie, wenn Sie wissen, dass Sie etwas kaputt gemacht haben. Die Leute können sagen, "Unit-Tests sollten schnell sein", und fahren mit Prinzipien und Entwurfsmustern und -methoden fort, aber in der Realität ist es manchmal besser, die Computer, die wir für sich wiederholende, monotone Aufgaben entwickelt haben, diese ausführen zu lassen und sich nur dann daran zu beteiligen, wenn sie beteiligt sind Sagen Sie uns, dass sie etwas gefunden haben.

TZHX
quelle
3
Unit - Tests Tests Code nicht Konfigurationen. Es wäre sehr träge von Ihnen, einen neuen Test hinzuzufügen und ihn über die Mauer zu werfen, ohne ihn zuerst lokal auszuführen ...
Robbie Dee
33
@RobbieDee Ich fürchte, ich kann deinen Standpunkt nicht erkennen? Ich schlage nicht vor, neue Tests zu erstellen, ohne sie lokal zu testen, oder Dinge blindlings der Quellcodeverwaltung zu überlassen, ohne sie selbst zu testen, und ich würde die Tests auf meinem eigenen Computer ausführen - aber "Konfiguration" muss auf konsistentes Verhalten getestet werden , und es ist besser, dies relativ schnell zu tun, wenn sich der Entwickler noch in diesem Bereich befindet, als ein Problem zu finden, wenn das Team, das überwiegend Macs verwendet, viertausend Meilen entfernt aufwacht und seine Kopien aktualisiert.
TZHX
7
@RobbieDee Ich würde sagen, TZHX würde alle Tests lokal ausführen, wenn sie dies könnten, aber sie können es nicht . Da TZHX dies nicht kann, führen sie einige Tests lokal durch (z. B. Tests, die auf ihrem Entwicklungssystem ausgeführt werden können und kurz genug oder für den geänderten Code am relevantesten sind) und lassen den vollen Akku auf dem CI-System laufen. Ziemlich vernünftig.
Muru
11
@RobbieDee: Er glaubt an Unit-Tests. Also testet er sie auf seinem Macbook Air, übergibt sie und checkt ein. Die CI-Server, auf denen Red Hat, Solaris und Windows ausgeführt werden, führen diese Tests erneut aus. Ist es nicht schön zu wissen, dass das, was Sie getestet haben, auch auf Produktionsplattformen funktioniert?
Slebetman
2
@RobbieDee: Ich habe oft Unit-Tests geschrieben, die für einen bestimmten Compiler auf einer bestimmten Plattform spezifisch waren. Betrachten Sie beispielsweise ein Grafiksubsystem, das AMD-spezifische CPU-Anweisungen (des Intel-Konkurrenten) verwendet, die nur in g ++ (dem GNU C ++ - Compiler) Version 4.5 oder neuer verfügbar sind, aber ich arbeite zufällig mit einer Atom-CPU und ICC (dem Intel C ++) Compiler). Es wäre Unsinn, die AMD / g ++ 4.5-Tests jedes Mal auf diesem Computer auszuführen, aber es handelt sich um Code, der vor der Veröffentlichung getestet werden muss. Außerdem muss mein eigener CPU-unabhängiger Code auf ordnungsgemäße Interoperabilität getestet werden. Klar, es gibt VMs und Emulatoren, ...
Phresnel
23

Abgesehen von der ausgezeichneten Oded-Antwort:

  • Sie testen den Code aus dem Repository . Möglicherweise funktioniert es auf Ihrem Computer mit Ihren Dateien, die Sie vergessen haben, festzuschreiben. Dies hängt möglicherweise von einer neuen Tabelle ab, die nicht über das Erstellungsskript verfügt (z. B. in Liquibase), sowie von einigen Konfigurationsdaten oder Eigenschaftendateien.
  • Sie vermeiden Code-Integrationsprobleme. Ein Entwickler lädt die letzte Version herunter, erstellt einen Unit- und Integrationstest, fügt Code hinzu, besteht alle Tests auf seinem Computer, schreibt fest und schiebt. Ein anderer Entwickler hat genau das Gleiche getan. Beide Änderungen sind für sich genommen richtig, verursachen jedoch beim Zusammenführen einen Fehler. Dies kann das Zusammenführen des Repository sein oder nur, dass es nicht als Konflikt erkannt wird. Zum Beispiel löscht Dev 1 eine Datei, die überhaupt nicht verwendet wurde. Dev 2-Codes gegen diese Datei und Tests ohne Dev 1-Änderungen.
  • Sie entwickeln ein Skript, das automatisch aus dem Repository bereitgestellt wird. Ein universelles Skript zu erstellen und bereitzustellen, löst viele Probleme. Einige Entwickler haben möglicherweise eine Bibliothek oder Kompilierungsoption hinzugefügt, die nicht von allen geteilt wird. Dies spart nicht nur Zeit, sondern macht die Bereitstellung auch sicher und vorhersehbar. Darüber hinaus können Sie in Ihrem Repository auf Version 2.3.1 zurückgreifen und diese Version mit einem Skript bereitstellen, das mit dieser Version funktioniert. Es enthält Datenbankobjekte wie Ansichten, gespeicherte Prozeduren, Ansichten und Trigger, die versioniert werden sollten. (Oder Sie können nicht zu einer funktionsfähigen Version zurückkehren.)
  • Andere Tests : Wie Integration, Leistung und End-to-End-Tests. Dies kann langsam sein und Testtools wie Selen beinhalten. Möglicherweise benötigen Sie einen vollständigen Datensatz mit einer echten Datenbank anstelle von Scheinobjekten oder HSQL.

Ich habe einmal an einer Firma gearbeitet, die aufgrund des Zusammenführungs- und Bereitstellungsprozesses viele Fehler bei der Bereitstellung hatte. Dies wurde durch ein seltsames Propietary-Framework verursacht, das das Testen und CI erschwerte. Es war keine erfreuliche Erfahrung, festzustellen, dass Code, der bei der Entwicklung perfekt funktioniert, nicht direkt in der Produktion ankam.

Borjab
quelle
Ja, einfach zu vergessen, einige der Änderungen zu übernehmen, ist weit verbreitet. Ich würde sagen, dass es die beliebteste Methode ist, zu vergessen, neue Dateien mit "svn add" zu versehen, und daher zu vergessen, sie später festzuschreiben, um einen fehlgeschlagenen automatischen Build zu erhalten.
Sharptooth
22

Das würde man denken, nicht wahr? Aber Entwickler sind Menschen, und manchmal vergessen sie es.

Außerdem können Entwickler häufig nicht den neuesten Code abrufen. Ihre letzten Tests könnten dann beim Einchecken gut verlaufen, wenn jemand anderes eine Änderung vornimmt.

Ihre Tests basieren möglicherweise auch auf einer lokalen (nicht aktivierten) Ressource. Etwas, das Ihre lokalen Unit-Tests nicht erfassen würden.

Wenn Sie der Meinung sind, dass all das phantastisch ist, gibt es eine Ebene über CI (mindestens auf TFS) mit dem Namen Gated, in der Builds mit fehlgeschlagenen Tests zurückgestellt und nicht für die Codebasis festgeschrieben werden.

Robbie Dee
quelle
7
Ich habe mehr Oops gesehen, die ich vergessen habe, zu begehen, dass CI-Fehler, die ich zugeben möchte.
Dan Neely
@DanNeely Um fair zu sein, es ist besser, wenn der Build-Manager auf deinen Hintern tritt, weil du vergessen hast, ihm / ihr etwas zu erzählen ... :-)
Robbie Dee
3
Das ist einer der Gründe, warum ich CI liebe. Das Finden und Reparieren Ihrer eigenen Ooops ist viel besser, als wenn jemand anderes sie für Sie findet.
Dan Neely
14

Bis etwas zum Meister wird

Normalerweise richte ich mein CI so ein, dass es bei jedem einzelnen Commit ausgeführt wird. Zweige werden erst mit dem Master zusammengeführt, wenn der Zweig getestet wurde. Wenn Sie Tests auf dem Master ausführen möchten, wird ein Fenster geöffnet, in dem der Build unterbrochen werden kann.

Bei der Ausführung der Tests auf einem CI-Computer geht es um reproduzierbare Ergebnisse. Da der CI-Server eine bekannte saubere Umgebung aufweist, die von Ihrem VCS abgerufen wurde, wissen Sie, dass die Testergebnisse korrekt sind. Bei lokaler Ausführung können Sie möglicherweise vergessen, den für die Übergabe erforderlichen Code festzuschreiben, oder nicht festgeschriebenen Code, der die Übergabe veranlasst, wenn sie fehlschlagen sollten.

Außerdem können die Entwickler Zeit sparen, indem verschiedene Suites parallel ausgeführt werden, insbesondere wenn es sich um langsame, mehrminütige Tests handelt, die nach jeder Änderung wahrscheinlich nicht lokal ausgeführt werden.

Bei meiner aktuellen Arbeit wird unser Produktionseinsatz darauf ausgerichtet, dass CI alle Tests besteht. Die Bereitstellungsskripts verhindern die Bereitstellung, sofern sie nicht übergeben werden. Dies macht es unmöglich, versehentlich zu vergessen, sie auszuführen.

Da ich Teil des Workflows bin, werden auch die Entwickler entlastet. Führen Sie als Entwickler in der Regel bei jeder Änderung einen Linter-, Static-Analyzer-, Unit-Test-, Code-Coverage- und Integrationstest durch? Ich kann, ganz automatisch und ohne darüber nachdenken zu müssen - das reduziert die Entscheidungsermüdung.

Daenyth
quelle
1
Sie sollten keine langsamen Unit-Tests durchführen - dies verstößt gegen die ERSTEN Prinzipien.
Robbie Dee
4
@RobbieDee: Ich denke, dass normalerweise der CI-Server alle Tests ausführt, nicht nur die Komponententests.
RemcoGerlich
4
@RobbieDee: Theoretisch sind alle Unit-Tests schnell. In der Praxis .... Unabhängig davon kann und sollte CI alle Tests ausführen - Linters, statische Analysen, Komponententests, Integrationstests.
Daenyth
2
@RobbieDee Offensichtlich variieren die Besonderheiten der Konfiguration von Team zu Team. Selbst wenn die Builds mehrere Minuten dauern, ist es häufig möglich, mehrere dieser Builds gleichzeitig auszuführen. Bei einer einzigen monolithischen Codebasis könnte dies ein größerer Nachteil sein, aber IME ist dies keine Barriere.
Daenyth
1
@RobbieDee Ich denke, es hängt mehr von deiner Architektur ab. Ich habe gesehen, wie es für ein Ingenieurteam von ~ 80 Mitarbeitern funktioniert, aber das sind genau definierte Unterteams für Produktbereiche.
Daenyth
4

Durch die Zeit , etwas zu meistern wird verpflichtet, ein Entwickler sollten bereits alle Unit - Tests laufen ... aber was ist, wenn sie nicht haben? Wenn Sie die Komponententests nicht auf dem CI-Server ausführen, werden Sie es erst erfahren, wenn eine andere Person die Änderungen auf ihren Computer überträgt und feststellt, dass die Tests nur für sie durchgeführt wurden.

Darüber hinaus hat der Entwickler möglicherweise einen Fehler gemacht und auf eine lokale Ressource verwiesen, die für seinen Computer spezifisch ist. Wenn sie den Code einchecken und der CI-Lauf fehlschlägt, wird das Problem sofort erkannt und kann behoben werden.

David Arno
quelle
3

Unter der Annahme, dass Entwickler (im Gegensatz zu anderen Antworten) sehr diszipliniert sind und Unit-Tests durchführen, bevor sie sich verpflichten, kann dies mehrere Gründe haben:

  • Das Ausführen von Unit-Tests kann einige Zeit in Anspruch nehmen. Beispielsweise kann die Ausführung von Unit-Tests mit Memory Checker (wie Valgrind) viel länger dauern. Obwohl alle Komponententests bestanden wurden, kann die Speicherprüfung fehlschlagen.
  • Das Ergebnis ist für einige spezielle Einstellungen nicht so wichtig. Beispielsweise erfordert das Ausführen von Komponententests zum Überprüfen der Codeabdeckung spezielle Kompilierungsflags. Für normale Entwickler ist die Codeabdeckung nicht so wichtig - es ist eher für Leute, die darauf achten, dass der Code eine bestimmte Qualität beibehält, wie z. B. Team-Leads.
BЈовић
quelle
3

Es ist möglich, sich Fälle vorzustellen, in denen die Änderung A den Test nicht unterbricht und die Änderung B den Test nicht unterbricht, A und B jedoch zusammen . Wenn A und B von verschiedenen Entwicklern erstellt wurden, erkennt nur der CI-Server den neuen Fehler. A und B können sogar zwei Teile desselben längeren Satzes sein.

Stellen Sie sich einen Zug vor, der von den beiden Lokomotiven A und B gefahren wird. Vielleicht ist einer mehr als genug, und dies ist die Lösung, die angewendet werden muss. Wenn jedoch die beiden "Korrekturen" angewendet werden, um beide zu entfernen, bewegt sich der Zug nicht.

Außerdem führen nicht alle Entwickler alle Unit-Tests durch, während die meisten guten Entwickler dies tun.

h22
quelle
2

Stellen wir eine äquivalente Frage:

Warum sollten Sie den Code auf einem CI-Server erstellen?

Sicherlich hat ein Entwickler den Code bereits erstellt und alle Fehler behoben, die möglicherweise bei seinem neuen Code aufgetreten sind, als sich etwas für master entschieden hat. Ist das nicht der Sinn der Bauordnung? Ansonsten haben sie nur fehlerhaften Code geschrieben.


Für CI gibt es mehrere Gründe, aber der Hauptpunkt von CI besteht darin, eine Vorstellung davon zu bekommen, wie der Status des Codes im Laufe der Zeit aussieht. Der Hauptvorteil (von mehreren), den dies bietet, ist, dass wir herausfinden können, wann der Build abbricht, herausfinden, was ihn gebrochen hat, und ihn dann reparieren können.

Warum verwenden wir überhaupt CI, wenn der Code nie kaputt ist? Um Builds zum Testen bereitzustellen, sind nächtliche Builds ausreichend.

Peter
quelle