Alternative zur Anzeige "Passing / Broken Build"?

14

Wenn eine kontinuierliche Integration die Tests bei jedem Commit ausführt, ist es eine bewährte Methode, alle Tests zu jeder Zeit bestehen zu lassen (auch bekannt als "Den Build nicht unterbrechen").

Ich finde einige Probleme damit:

Zum Beispiel kann man einem Open-Source-Projekt nicht helfen, indem man Tests erstellt, die Tickets entsprechen. Ich weiß, wenn ich einem Open-Source-Projekt, das einen fehlgeschlagenen Test enthält, eine Pull-Anforderung vorschlage, wird der Build als fehlgeschlagen markiert, und das Projekt möchte nicht, dass dieser in seinem Repository zusammengeführt wird, da er "den Build unterbricht".

Und ich glaube nicht, dass es eine schlechte Sache ist, fehlerhafte Tests in Ihrem Repo zu haben , es ist, als hätten Sie offene Probleme in Ihrem Tracker. Dies sind nur Dinge, die darauf warten, repariert zu werden.

Das gleiche gilt für eine Firma. Wenn Sie mit TDD arbeiten, können Sie keine Tests schreiben, festschreiben und dann den Logikcode schreiben, der den Test erfüllt. Das heißt, wenn ich 4-5 Tests auf meinem Laptop geschrieben habe, kann ich sie nicht vor Urlaubsantritt festschreiben. Niemand kann meine Arbeit zurücknehmen. Ich kann sie nicht einmal mit einem Kollegen "teilen", außer indem ich sie zum Beispiel per E-Mail sende. Es wird auch verhindert, dass eine Person die Tests schreibt und die andere Person das Modell schreibt.

All das zu sagen, missbrauche / missverstehe ich den Build-Prozess / kontinuierliche Integration? Es scheint mir, dass "Bestehen" / "Nichtbestehen" ein zu enger Indikator ist.

Gibt es eine Möglichkeit, die kontinuierliche Integration und die TDD-Kompatibilität zu gewährleisten?

Vielleicht gibt es eine Standardlösung / -praxis zur Unterscheidung zwischen "neuen Tests" (die fehlschlagen können) und "Regressionstests" (die nicht fehlschlagen sollten , weil sie früher funktionierten)?

Matthieu Napoli
quelle
1
Haben Sie eine Anzeige, die anzeigt, ob die Anzahl der fehlgeschlagenen Tests in der letzten Stunde (oder so) gestiegen (rot) oder gesunken (grün) ist.
Joachim Sauer
2
Ich bin kein TDD / ALM-Spezialist (daher der Kommentar anstatt eine Antwort), aber ich denke, Ihr Problem kann mit privaten Filialen / Feature-Filialen gelöst werden. Arbeiten Sie an Feature A? Verzweigen Sie ihn, bearbeiten Sie den Zweig (mit Kollegen), und wenn Sie fertig sind, fügen Sie ihn in den durchgehend integrierten Kofferraum ein.
Avner Shahar-Kashtan
@JoachimSauer Ja, aber wird eine solche Metrik in einem Großprojekt standardisiert / verwendet? Ich versuche zu verstehen, warum die meisten Projekte (und CI-Tools) so funktionieren.
Matthieu Napoli
Ich denke, das richtige Kriterium für "Tests, die fehlschlagen können" ist nicht "neue Tests", sondern "Tests auf bekannte offene Probleme". Ich kann sehen, wie nützlich diese Tests sind - ich kann auch feststellen, dass diese Tests im CI-Build NICHT nützlich sind, da sie die Bedeutung des Tests verschlechtern, der dort bestanden / nicht bestanden wurde (Sie möchten nur Tests ausführen, für die tatsächlich jemand Zeit aufgewendet hat zum Bestehen bringen).
Joris Timmermans
@ MadKeithV Genau
Matthieu Napoli

Antworten:

12

Ich verstehe, wohin Sie kommen, aber diese Probleme werden normalerweise auf andere Weise gelöst. Es gibt einen guten Grund, warum dies das Standardprotokoll ist. Wenn jemand Code einreicht, der nicht kompiliert wird, hat jeder, der seinen Code aktualisiert, ein Programm, das nicht kompiliert wird . Dazu gehören Programmierer, die derzeit an etwas völlig anderem arbeiten und sich irgendwie in einer Situation befinden, in der sie warten müssen, bevor sie kompilieren und testen können, woran sie arbeiten.

Das Standardprotokoll sieht vor, dass Sie Änderungen auch bei vollständiger oder unvollständiger Arbeit vornehmen können, sofern diese kompiliert werden, sodass Programmierer ihren Code bei Bedarf täglich aktualisieren können.

Ich sehe jedoch immer noch, worauf du hinaus willst. Manchmal möchten Sie ein Commit durchführen, um Ihren Code einfach zu speichern . Aus diesem Grund unterstützen die meisten Quellrepositorys die Verzweigung. Auf diese Weise können Sie eine private Zweigstelle erstellen, diese bearbeiten, ohne andere zu stören, und nach Abschluss der Arbeit in den Stamm einbinden. Auf diese Weise können Sie ein Commit ausführen, wenn Sie möchten, ohne dass der mit dem Abbruch des Builds verbundene Spielraum verloren geht.

Wenn dies nicht geeignet ist, können Sie mit GIT ein Commit (Pushing) für Repositorys auf Ihrem lokalen Computer ausführen. Es ist jedoch denkbar, dass sich das Repository an einem beliebigen Ort befindet. Sie können ein Repository für möglicherweise teilweise / unvollständige Arbeit und ein anderes Repository für abgeschlossene Arbeit erstellen und auf diesem Repository einen nächtlichen Build hinzufügen.

Auch hier kann ich die Wichtigkeit nicht genug betonen. Übergebe niemals kaputten Code an den Trunk! Ihre Beiträge können sich nicht auf die Arbeit anderer Programmierer auswirken.

Bearbeiten

Ich sehe, dass Sie gebrochene Tests beabsichtigt haben, aber meiner bescheidenen Meinung nach gibt es wenig Unterschied. Der Sinn eines Tests besteht darin, festzustellen, ob ein bestimmter Aspekt eines Programms bestanden wurde oder nicht. Wenn es immer fehlschlägt und Sie nichts tun, hat der Test im herkömmlichen Unit-Test keine Wirkung. Wenn Sie es verwenden, um eine andere Metrik auszuführen, die nicht unbedingt ein "fehlgeschlagenes" Commit nach sich zieht, wenn ein solcher Test fehlschlägt, würde ich Ihnen dringend empfehlen, einen anderen Weg zu finden, um dasselbe zu tun.

Andernfalls riskieren Sie, dass der Test nie in Betracht gezogen wird oder dass Ihre Programmierkollegen fehlgeschlagene Builds ignorieren, wenn dies zu einem Fehlschlagen Ihres Builds führt. Es ist wichtiger, dass Programmierer erkennen, wann sie einen Build gebrochen haben, als einen Test durchzuführen, der keinen wirklichen Einblick bietet und möglicherweise nur zu schlechten Praktiken führt.

Neil
quelle
1
In der Tat legen Sie Wert auf Zweigstellen. Aber ich spreche nie davon, kaputten Code zu schreiben, sondern nur Tests zu bestehen. Zum Beispiel könnte ich einem Open-Source-Projekt helfen, indem ich Tests für eingehende Tickets erstelle, auch wenn ich nicht weiß, wie ich sie beheben kann. Das spart den Betreuern etwas Zeit.
Matthieu Napoli
Wenn ich an demselben Projekt arbeite wie Sie und Sie einen fehlgeschlagenen Test hochladen, habe ich jetzt einen Build mit einem fehlgeschlagenen Test. Möglicherweise lösche ich Ihren Test, da diese Funktionalität noch nicht implementiert ist, oder entscheide mich, die Funktion zu implementieren und dann auf Ihrem Code herumzustampfen und Zeit zu verschwenden. Wenn es eine Kultur gäbe, die dies tut, könnte diese Art von Reaktion vermieden werden, aber dann würde es jeder tun, und selbst wenn alle Ihre Tests bestanden sind, tun es nicht alle meine. In diesem Fall würde der Build immer fehlerhafte Tests haben. Ich sehe keinen Vorteil.
Michael Shaw
the build would always have failing testsgenau! Aber ist das so eine schlechte Sache? Unsere einzige Metrik ist "Der Build ist kaputt oder nicht", aber Ihr Code könnte voll von bekannten Fehlern sein , sodass das eigentlich nichts bedeutet, außer dass es keine Regression gibt. In einer perfekten Welt hätte jedes Tracker-Problem einen Test (das Reproduzieren ist einfacher als das Beheben). Das Positive wäre also, dass 35 Tests / 70% aller Tests bestanden werden, dass Branch-A es auf 40 Tests (80%) ohne Regression verbessert und dass Branch-B Regressionen aufweist. Heute kann man nur sagen, dass Master und Branch-A in Ordnung sind und Branch-B defekt ist.
Matthieu Napoli
@Matthieu Ich verstehe, worauf du hinaus willst. Klingt so, als ob Sie eine spezielle Kategorie benötigen oder etwas, das besagt: "Hey, wenn dieser Test fehlschlägt, ist es in Ordnung. Wir wissen darüber Bescheid. Aber wir wollen immer noch, dass er ausgeführt wird. Wenn er erfolgreich ist, ist das sogar noch besser und wir sollten die spezielle Kategorie entfernen, weil wir kümmern uns jetzt darum, ob es kaputt geht "
Earlz
@Earlz Genau! Ich frage mich, ob es "irgendwo von jemandem ausgeführt wird" und ob es Tools gibt, die dies unterstützen (CI- und Unit-Testing-Bibliotheken). Wenn ich diese Tests nur mit klassischen CI- und Unit-Testing-Tools kategorisiert habe, wird der Build immer erstellt Trotzdem scheitern und ich sehe keinen Unterschied zwischen den fehlgeschlagenen Tests, und so wird es nicht nützlich sein: /
Matthieu Napoli
4

Wie können Sie bei einem Master-Zweig mit fehlgeschlagenen Tests sicher sein, dass Sie keine Bugs eingeführt haben, ohne diese Liste mit früheren Builds zu vergleichen?

Es reicht nicht aus, nur die Anzahl der fehlgeschlagenen Tests zu protokollieren: Sie können einen Test reparieren und einen anderen brechen. Und wenn Sie im Urlaub sind, wird es anderen nicht klar sein, wenn sie sich den fehlerhaften Build ansehen.

Halten Sie Ihre Hauptniederlassung jederzeit sauber und grün . In einer Filiale arbeiten. Bewahren Sie die Filiale in einem separaten Job unter CI auf und lassen Sie Tests nach Herzenslust nicht bestehen. Mach den Meister nicht kaputt.

Lassen Sie den Prüfer der Zweigstelle Ihre Zweigstelle nur zusammenführen, wenn alle Tests bestanden wurden. (Stärker: Der Prüfer kann Ihren Zweig nur dann zusammenführen, wenn das Ergebnis der Zusammenführung des Zweigs zum Master alle Tests besteht!)

Frank Shearar
quelle
2
Simply tracking the number of failing tests is insufficientDas ist nicht die einzig mögliche Metrik. Zum Beispiel: Branch-A improves it to 40 tests (80% passing) with no regression. Keine Regression bedeutet, dass zuvor bestandene Tests immer bestanden werden. Kurz gesagt, ein Test kann scheitern, solange er noch nicht bestanden wurde. Es scheint mir, dass wir gute Dinge vermissen, indem wir uns darauf beschränken, nicht bestandene Tests in Hauptzweigen zu verbieten. (Natürlich würde es erfordern, dass die Werkzeuge anders funktionieren: Unit-Tests, CI, ...)
Matthieu Napoli
Ich stehe immer noch zu meinem Standpunkt: Der Meister sollte immer grün sein, weil er klar und eindeutig ist. In jedem Fall schlagen Markertests fehl ... in einem Feature-Zweig. C Ich kann die Leute immer wieder an offene Fehler erinnern.
Frank Shearar
Ich denke, was Matthieu vorschlägt, ist eine etwas andere Definition von "grün", die nicht davon abweicht, dass der Meister immer grün ist. Es ist mir nicht klar, dass es keinen Sinn ergibt - es würde natürlich einige nicht ganz triviale Werkzeuge zum Verfolgen benötigen. (Müssen Sie eine Änderung zurücksetzen, die diesen Test bestanden hat? Pech, wenn das bedeutet, dass der Zustand plötzlich rot ist ...)
Christopher Creutzig
NUnit hat das Konzept eines ignorierten Tests. Das könnte eine Alternative sein: Sie werden nicht ausgeführt, damit sie nicht versagen, aber sie werden trotzdem als ignoriert gemeldet.
Frank Shearar
2

Es gibt Möglichkeiten, Ihre Probleme zu lösen, ohne gut verstandene und akzeptierte Praktiken zur kontinuierlichen Integration zu verwerfen.

Ich beginne mit dem Problem, einen "kaputten Test" zu erstellen, der einem Ticket entspricht. Eine Lösung besteht darin , einen oder mehrere Bruchtests zu erstellen, die das Problem aufdecken, und das Problem dann tatsächlich zu beheben , damit sie wieder in der Hauptcodezeile zusammengeführt werden können. Die zweite Lösung besteht darin , die fehlerhaften Tests zu haben, aber eine Art Ignorierflag zu verwenden, damit sie nicht tatsächlich ausgeführt werden und den Build unterbrechen. Fügen Sie möglicherweise einen Kommentar oder eine spezielle Anmerkung hinzu , die deutlich macht, dass dies ein fehlerhafter Test für ist Ticket#N. Fügen Sie dem Ticket selbst auch eine Notiz hinzu, die auf die erstellten Tests verweist, die darauf warten, nicht ignoriert und ausgeführt zu werden. Dies würde einer Person helfen, das Ticket zu reparieren, wäre aber auch keine rote Fahne für jemanden, der auf den Test stößt.

Und auf dein nächstes Problem mit TDD. Bei TDD geht es darum, einen kleinen Test zu schreiben und dann einen kleinen Codeabschnitt, um diesen Test zu bestehen . Dann iterieren Sie weiter, bis Sie ein kleines Funktionsmodul haben. Ich habe das Gefühl, wenn Sie 4-5 Tests schreiben und dann in den Urlaub fahren, könnten Sie es falsch machen. Sie können ein Programm so mit jemandem koppeln, dass einer von Ihnen den Test schreibt, der andere den entsprechenden Code. Sie sollten jedoch nicht das Haupt-Codezeilen-Repository verwenden, um diesen Code für Sie beide freizugeben, bevor ein abgeschlossenes Modul für das Commit bereit ist. Wie andere vorgeschlagen haben, würde eine gemeinsame Niederlassung Ihre Probleme dort lösen.

Der Versuch, das Mantra der kontinuierlichen Integration zu durchbrechen, kann zu unerwarteten und beängstigenden Pfaden führen. Zum Beispiel, was bedeuten würde , Code - Coverage in dieser Art von Umgebung ? Wie würden Entwickler nicht glauben, dass das System viele " Broken Windows " hat ? Wie würde man eine Änderung vornehmen, den Test durchführen und wissen, ob tatsächlich etwas Neues kaputt geht oder nur das alte Zeug?

c_maker
quelle
Sie brauchen kein Werkzeug, um es mit der Person zu teilen, mit der Sie ein Paar programmieren - geben Sie einfach die Tastatur ab. Wenn Sie verschiedene Computer verwenden, stimmt das nicht, es ist einfach keine "Paarprogrammierung".
Christopher Creutzig
1

Ich denke, Ihr grundlegendes Problem ist, dass Sie Testergebnisse als Teil des Builds einbinden. Während offensichtlich einige Leute mit Ihnen einverstanden sind, tun andere nicht. Der Build wird abgebrochen, wenn er nicht erstellt wird. Nicht, wenn es nicht fehlerfrei erstellt wird.

Betrachten Sie ein großes Projekt wie Windows oder Linux oder sogar etwas wie Firefox - denken Sie, dass es fehlerfrei ausgeliefert wird? Natürlich nicht. Jetzt machen diese Projekte keine TDD, aber das ist wirklich irrelevant - TDD ändert zwei grundlegende Fakten nicht: Es gibt Fehler und es braucht Zeit, um sie zu beheben. Zeit, die sich ein Projekt (Open Source oder nicht) nicht leisten kann, um Fehler mit niedriger Priorität zu beseitigen. KDE hatte kürzlich einen über zehn Jahre alten Fehler behoben. Wann haben Sie das letzte Mal jemanden sagen hören: "Ich bin froh, dass wir ein Jahrzehnt darauf gewartet haben, unser Projekt zu liefern"?

In gewisser Weise macht es TDD wahrscheinlich einfacher, mit Fehlern zu versenden - weil Sie besser verstehen, was der Fehler ist. Wenn Sie genau definieren können, was den Fehler verursacht, haben Sie eine hervorragende Grundlage, um die Kosten für die Fehlerbehebung abzuwägen.

Meine Empfehlung ist es, ein Projekt zu finden, dem Rot und Grün nichts ausmachen.

jmoreno
quelle
1
 > a common best practice is to have all the tests passing (green) at all times.

Ich bevorzuge, dass alle Tests nicht fehlschlagen (nicht rot).

Mit dieser etwas anderen Definition können Sie auch Tests definieren, die sind

  • noch nicht implementiert (grau in nunit wenn es eine NotImplementedException gibt)
  • bekanntermaßen fehlgeschlagen = "muss erledigt werden" durch Markieren / Kommentieren des Tests als ignoriert (gelb)

Wenn Sie diese in das Repository einchecken, ist Ihr fortlaufender Build nicht beschädigt und daher gültig.

k3b
quelle
0

Sie können zwei verschiedene CI-Build- "Konzepte" in Betracht ziehen.

  1. Regelmäßige CI-Builds. Der reguläre CI-Build sollte nur die Tests kompilieren und ausführen, für die Code geschrieben wurde, damit sie bestanden werden, sodass CI-Berichte über bestandene / nicht bestandene Tests ein eindeutiger Indikator für eine Regression gegenüber dem zuvor akzeptierten Status des Codes sind.
  2. Ein "zukünftiger" CI-Build. Dieser Build kompiliert und führt nur die Tests aus, für die kein Code speziell geschrieben wurde, damit sie bestanden werden. Es kann mehrere Gründe geben, einen solchen Test durchzuführen:

    • Über den Issue Tracker können Tests für bestimmte Fehlerfälle hinzugefügt werden, für die noch keine Fehlerbehebung versucht wurde. Es ist eindeutig nützlich, bereits einen kodifizierten, laufenden Test für ein Problem zu haben, auch ohne eine Fehlerbehebung.

    • Es wurden Tests für neue erforderliche Funktionen hinzugefügt, die noch nicht implementiert wurden.

    • Oft ist es einfacher zu wissen, wie ein Fehler oder eine Funktion getestet wird, als wie die Funktion oder die Fehlerbehebung implementiert wird. Eine Trennung der beiden Schritte durch Übergabe des Tests an die Quellcodeverwaltung kann hilfreich sein, um sicherzustellen, dass keine Informationen verloren gehen.

Wie in "Standard" CI würde das Team in der regulären Entwicklungsumgebung nur die täglichen Build-Ergebnisse des regulären Builds betrachten.

Das Team kann auch die Entwicklung der Testfälle aus dem CI-Build "Zukunft" im Auge behalten, um insbesondere festzustellen, ob durch Änderungen am regulären CI tatsächlich Probleme aus dem Build "Zukunft" behoben wurden, die ein Hinweis auf ein wichtiges Problem sein können zugrunde liegendes Problem oder Designverbesserung.

Wenn ein Teammitglied zusätzliche Zeit zur Verfügung hat, kann es versuchen, eines der Probleme aus "Zukunft" zu beheben und es erfolgreich auf "Normal" zu migrieren (während der Status der Problemverfolgung aktualisiert wird).

Joris Timmermans
quelle
0

Und ich glaube nicht, dass es eine schlechte Sache ist, fehlerhafte Tests in Ihrem Repo zu haben, es ist wie offene Probleme in Ihrem Tracker. Dies sind nur Dinge, die darauf warten, repariert zu werden.

Das Problem besteht darin, dass Tests nicht fehlschlagen. Es ist ein einfacher, kontextloser Indikator für Regression. Aka: Kann ich als Entwickler einen einzelnen Indikator überprüfen und wissen, ob ich einen Regressions- oder einen Breaking-Code eingeführt habe?

In dem Moment, in dem Sie das Konzept der "weichen" Fehler einführen (es ist in Ordnung, wir arbeiten daran / sind noch nicht implementiert / warten auf die neue Version / es wird wieder vergehen, sobald dieser andere Build behoben ist), benötigen Sie Jeder, der den Test ausführen oder ansehen könnte, um den erwarteten Zustand zu kennen. Was sich in einem ausreichend großen Team von Stunde zu Stunde ändern wird: Ihr Indikator wird bedeutungslos. In einem kleineren Kontext (z. B. Team Private Integration Test) denke ich, dass es wie eine technische Verschuldung ist und in Ordnung ist - muss nur verwaltet werden.

Die Art und Weise, wie die meisten Tools "grün / bestanden" adressieren, spiegelt das erwartete Ergebnis wider - nicht, dass der Code funktioniert:

  • Fitness hat das Konzept des erwarteten Scheiterns.
  • JUnit hat @Ignored / @Test (expect =)
  • Gurke hat den Status "noch nicht implementiert" (oder wie auch immer es heißt)

Diese haben ihre eigenen Probleme (wie unterscheidet man zwischen "Ja, wir wissen, dass es kaputt ist, daran zu arbeiten" und "Das richtige Verhalten ist eine Ausnahme") - aber sie helfen.

ptyx
quelle
0

Ich benutze übersprungene Tests.

In dem speziellen Unit-Testing-Framework, das ich verwende, kann ich eine SkipTest-Ausnahme auslösen. Der Test wird nicht tatsächlich ausgeführt, und sein Fehler wird den Build nicht beschädigen. Ich kann jedoch die Anzahl der übersprungenen Tests sehen und sehen, ob in diesem Bereich noch etwas zu tun ist.

Winston Ewert
quelle