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)?
quelle
Antworten:
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.
quelle
the build would always have failing tests
genau! 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.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!)
quelle
Simply tracking the number of failing tests is insufficient
Das 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, ...)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?
quelle
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.
quelle
Ich bevorzuge, dass alle Tests nicht fehlschlagen (nicht rot).
Mit dieser etwas anderen Definition können Sie auch Tests definieren, die sind
Wenn Sie diese in das Repository einchecken, ist Ihr fortlaufender Build nicht beschädigt und daher gültig.
quelle
Sie können zwei verschiedene CI-Build- "Konzepte" in Betracht ziehen.
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).
quelle
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:
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.
quelle
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.
quelle