Sie sollten die Codeabdeckung nicht automatisch erzwingen.
Dies ist wie das Erzwingen der maximalen Codezeilen pro Methode: Einverstanden, die meisten Methoden sollten weniger als beispielsweise 20 LOC betragen, aber es gibt gültige Fälle, in denen Methoden länger wären.
Auf die gleiche Weise kann die Ausrichtung auf einen bestimmten Prozentsatz der Codeabdeckung pro Klasse zu unerwünschten Konsequenzen führen. Zum Beispiel:
Boilerplate-Codeklassen oder Klassen, die von Codegeneratoren erstellt wurden, werden möglicherweise überhaupt nicht getestet. Entwickler zu zwingen, sie zu testen, hat keinen Vorteil und verursacht erhebliche Kosten in Bezug auf die dafür aufgewendete Zeit.
Einfache Code-Behandlung unwichtiger Teile der Anwendung muss nicht unbedingt getestet werden.
In einigen Sprachen kann ein Teil des Codes nicht getestet werden. Ich hatte diesen Fall in C # mit anonymen Methoden in einer Bibliothek, in der ich wirklich eine 100% ige Codeabdeckung haben wollte . Diese Fälle können für Entwickler demoralisierend sein.
Noch wichtiger ist, dass die Codeabdeckung proportional zu zwei Aspekten des Codes sein sollte: wie kritisch und wie kompliziert es ist :
Ein Teil des Codes mit einer komplizierten Logik, die Teil des Hauptmerkmals einer Anwendung ist, sollte besser sorgfältig getestet werden, da Fehler oder Regressionen wichtige Konsequenzen haben können.
Ein einfacher Code, der eine Funktion behandelt, die niemand verwendet, enthält möglicherweise grundlegende Tests, die nur grundlegende Fälle abdecken.
Natürlich können Sie die Codeabdeckung weiterhin als Maß verwenden , insbesondere um zu vergleichen, wie verschiedene Teams die Codeabdeckung erreichen: Es kann Teams geben, die weniger diszipliniert und beim Testen weniger zurückhaltend sind. In diesen Fällen möchten Sie diese Metrik möglicherweise mit anderen kombinieren, z. B. der Anzahl der Fehler, der Zeit, die für die Behebung von Fehlern aufgewendet wurde, oder der Anzahl der Anmerkungen während der Codeüberprüfung.
Möglicherweise möchten Sie auch bei einzelnen Projekten, bei denen dies sinnvoll ist (achten Sie darauf, Prototypen, generierten Code, CRUD usw. auszuschließen), zumindest eine gewisse Codeabdeckung (z. B. 60% ¹) erzwingen , damit Entwickler bestimmte Klassen als ausgeschlossen markieren können von der Codeabdeckung ist auch schön². In diesem Fall kann dies im Rahmen einer Überprüfung erfolgen, bei der ein Build fehlschlägt, wenn die Codeabdeckung unter dem erforderlichen Minimum liegt. Ich würde es in der Build-Phase tun, nicht in der Commit-Phase , da nicht erwartet wird, dass Sie während des Commits Unit-Tests ausführen .
¹ Ich würde 60% als angemessenes Minimum betrachten, basierend auf meiner Codebasis: Fast jedes Projekt oder jede Klasse mit weniger als 60% Codeabdeckung ist wirklich ungetestet . Dies kann von Sprache zu Sprache und von Unternehmen zu Unternehmen sehr unterschiedlich sein (in einigen Unternehmen sind 0% ein Standard). Besprechen Sie mit Ihrem Team, was normal und was für sie zu hoch ist . Vielleicht erreichen sie ständig 95% und können leicht 99% erreichen, oder sie haben Schwierigkeiten, ihre Codeabdeckung von 70% auf 75% zu erhöhen.
² Angesichts der Tatsache, dass bei Codeüberprüfungen eventueller Missbrauch festgestellt wird, sollten Sie keine Angst haben, Entwicklern diese Möglichkeit zu geben. Dies ähnelt der Möglichkeit, einige Teile des Codes von den Überprüfungen durch die Linters oder Stilprüfer auszuschließen. JSLint, StyleCop und Code Analysis sind drei Beispiele, bei denen der Ausschluss unterstützt wird und tatsächlich nützlich ist, ohne Missbrauch zu fördern.
Betrachten Sie den folgenden Code:
Es gibt keine Möglichkeit, einen Testfall zu erstellen, der diesen anderen Zweig erreicht. Wenn dies jedoch eine sicherheitskritische Flugsoftware wäre, wären die Leute im ganzen Fall des Autors, wenn dieser Schutz gegen das Senden eines negativen Wertes
sqrt
nicht vorhanden wäre. Typischerweise werden die Berechnungrsq = a*a + b*b
und die Extraktion der Quadratwurzel durch mehrere Codezeilen getrennt. In der Zwischenzeit kann ein kosmischer Strahl das Vorzeichenbit einschaltenrsq
.Tatsächlich hat die Flugsoftware das Äquivalent von
handle_this_impossible_event()
mehrfach aufgerufen . In der Regel müssen Sie die Steuerung auf einen redundanten Computer umstellen, den verdächtigen Computer ordnungsgemäß herunterfahren, den verdächtigen Computer neu starten und schließlich den verdächtigen Computer als Backup übernehmen. Das ist viel besser als der primäre Flugcomputer, der verrückt wird.Selbst in Flugsoftware ist es unmöglich, eine 100% ige Codeabdeckung zu erreichen. Die Leute, die behaupten, dies erreicht zu haben, haben entweder einen trivialen Code oder sie haben nicht genug Tests gegen diese unmöglichen Ereignisse.
quelle
a
undb
vorzeichenbehaftete 32-Bit-Ganzzahlen sind, können viele Werte wie 65535 und 65535 oder 40000 und 40000rsq
negativ sein.0.0
, was impliziert,a
undb
sind einige Gleitkomma-Typ. Bei Flugsoftware ist es unerlässlich, sich vor der Quadratwurzel einer negativen Zahl zu schützen, auch wenn Sie wissen, dass die Zahl nicht negativ sein kann. Kosmische Strahlung sind lästige Kleinigkeiten. In einem kürzlich durchgeführten Experiment ( das vor weniger als einer Woche gestartet wurde ) wird untersucht, ob ein Supercomputer auf der Internationalen Raumstation Software anstelle von Hardware zum Schutz vor kosmischer Strahlung (SEUs usw.) verwenden kann.0.0
.Die Testabdeckung ist eine nützliche Messgröße für den Gesamtzustand Ihres Projekts. Mit einer hohen Testabdeckung können Sie eine fundierte Entscheidung darüber treffen, ob die Software bei der Bereitstellung wie erwartet funktioniert. mit einer geringen Testabdeckung bedeutet dies, dass Sie nur raten. Es gibt Tools zum automatischen Messen der Abdeckung. Diese funktionieren normalerweise, indem das Programm in einem Debugging-Kontext ausgeführt wird oder indem Buchhaltungsvorgänge in den ausgeführten Code eingefügt werden.
Es gibt verschiedene Arten von Tests und verschiedene Arten von Abdeckungsmetriken. Zu den allgemeinen Abdeckungsmetriken gehören Funktionsabdeckung, Anweisungsabdeckung, Zweigabdeckung und Bedingungsabdeckung, obwohl es mehr gibt .
Einheit Tests prüfen , ob die Durchführung eines konzeptuellen Einheit (Modul, Klassen-, Methoden-, ...) sich nach seiner Spezifikation (in TDD, der Test ist die Spezifikation). Einheiten ohne eigene Komponententests sind eine rote Fahne, obwohl sie möglicherweise durch Tests im Integrationsstil abgedeckt werden.
Unit-Tests sollten eine nahezu vollständige Funktionsabdeckung implizieren. Da der Unit-Test die gesamte öffentliche Schnittstelle dieser Unit ausübt, sollte es keine Funktionen geben, die von diesen Tests nicht berührt werden. Wenn Sie Unit-Tests in eine vorhandene Codebasis einführen, ist die Funktionsabdeckung ein grober Fortschrittsindikator.
Ein Unit-Test sollte eine gute Abdeckung (75% –100%) anstreben. Die Anweisungsabdeckung ist eine Qualitätsmetrik für einen Komponententest. Eine vollständige Abdeckung ist nicht immer möglich, und Sie können Ihre Zeit wahrscheinlich besser nutzen, als die Abdeckung über 95% hinaus zu verbessern.
Zweig- und Zustandsabdeckung sind schwieriger. Je komplizierter oder wichtiger ein Code ist, desto höher sollten diese Metriken sein. Bei unspektakulärem Code reicht jedoch in der Regel eine hohe Abdeckung der Anweisungen aus (und dies impliziert bereits eine Zweigabdeckung von mindestens 50%). Ein Blick auf den Zustandsbericht einer Einheit kann dazu beitragen, bessere Testfälle zu erstellen.
Integrationstests prüfen, ob mehrere Einheiten korrekt miteinander arbeiten können. Integrationstests können sehr nützlich sein, ohne in einer Abdeckungsmetrik eine hohe Punktzahl zu erzielen. Während Integrationstests normalerweise einen großen Teil der Schnittstellen ihrer Einheit beanspruchen (dh eine hohe Funktionsabdeckung aufweisen), wurden die Interna dieser Einheiten bereits durch die Einheitentests abgedeckt.
Es ist eine gute Idee, Tests auszuführen, bevor Code in einem Hauptzweig zusammengeführt wird. Die Berechnung der Testabdeckungsmetriken für das gesamte Programm nimmt jedoch viel Zeit in Anspruch - dies ist eine gute Aufgabe für einen nächtlichen Build. Wenn Sie herausfinden können, wie dies zu tun ist, besteht ein guter Kompromiss darin, nur geänderte Tests oder Komponententests für geänderte Einheiten in einem Git-Hook auszuführen. Testfehler sind für nichts anderes als "Work in Progress" -Commits akzeptabel. Wenn ausgewählte Abdeckungsmetriken einen bestimmten Schwellenwert unterschreiten (z. B. Abdeckungsabdeckung unter 80% oder Einführung neuer Methoden ohne entsprechende Tests), sollten diese Probleme als Warnung behandelt werden, mit der Möglichkeit für den Entwickler, diese potenziellen Probleme zu beheben. Manchmal gibt es jedoch gute Gründe, diese Warnungen zu ignorieren, und Entwickler sollten dazu in der Lage sein.
Testen ist gut, aber zu viel davon kann nervig werden. Schnelles, relevantes Feedback kann dazu beitragen, die Aufmerksamkeit auf Qualität zu lenken, aber Sie möchten nicht, dass es der Wertschöpfung im Wege steht. Ich persönlich bevorzuge es, Tests manuell auszuführen, da ich dadurch schnelleres Feedback zu dem Teil bekomme, an dem ich arbeite. Vor der Veröffentlichung werde ich mich auf die Qualität konzentrieren, bei der ich statische Analysen, Profiler und Tools zur Codeabdeckung verwende, um Problembereiche zu finden (wobei einige dieser Schritte Teil einer Testsuite vor der Veröffentlichung sind).
quelle
Niemand hat Mutationstests erwähnt . Die Idee dahinter ist sehr praktisch und intuitiv.
Sie arbeiten, indem sie den Quellcode zufällig ändern (z. B. ">" in "<" umschalten) - daher Mutation - und prüfen, ob diese zufälligen Änderungen einen Test brechen.
Wenn dies nicht der Fall ist, ist entweder a) der betreffende Code möglicherweise nicht erforderlich, oder b) (wahrscheinlicher) dieser Code wird nicht durch einen Test abgedeckt, da das Brechen des Codes unentdeckt bleibt.
quelle
Daten zur Codeabdeckung können natürlich automatisch abgerufen werden, aber aus Gründen, die andere bereits erläutert haben, sollten keine automatischen Entscheidungen auf dieser Grundlage getroffen werden. (Zu verschwommen, zu viel Raum für Fehler.)
Das nächstbeste ist jedoch ein etablierter Prozess, bei dem der aktuelle Status des Projekts in Bezug auf die Codeabdeckung regelmäßig von Menschen überprüft wird, möglicherweise mit täglichen Berichten, die im Posteingang des Projektmanagers eingehen.
In Unternehmensumgebungen wird dies mit Tools für die kontinuierliche Integration wie Hudson, Jenkins usw. erreicht. Diese Tools sind so konfiguriert, dass sie das gesamte Projekt regelmäßig aus dem Quellcode-Repository auschecken, erstellen, die Tests ausführen und Berichte erstellen. Natürlich können sie so konfiguriert werden, dass die Tests im Codeabdeckungsmodus ausgeführt werden und die Ergebnisse in diese Berichte aufgenommen werden.
Jetbrains macht auch TeamCity, das mir etwas leichter erscheint und für kleinere Software-Shops geeignet ist.
So erhält der Projektmanager regelmäßig Berichte zur Codeabdeckung, verwendet sein eigenes Urteilsvermögen und fungiert bei Bedarf als Durchsetzer.
quelle
Die Codeabdeckung kann trotz allgemeiner Meinung automatisch überprüft werden. Die Purify-Toolsuite von Rational enthielt eine Codeabdeckungsfunktion. Es beruhte auf der Instrumentierung aller Funktionen (es arbeitete an den Binärdateien, aktualisierte jede Funktion oder rief mit etwas zusätzlichem Code auf), damit es Daten ausschreiben konnte, die dann dem Benutzer angezeigt wurden. Ziemlich coole Technologie, besonders zu der Zeit.
Aber selbst wenn wir uns wirklich sehr bemüht haben, eine 100% ige Abdeckung zu erreichen, haben wir nur ungefähr 70% geschafft! Es ist also eine sinnlose Übung.
In der Situation, Unit-Tests zu schreiben, halte ich eine 100% ige Abdeckung von Unit-Tests jedoch für noch sinnloser. Unit Test die Methoden, die Unit Test erfordern, nicht jeder Getter oder Setter! Beim Unit-Test sollte es darum gehen, die kniffligen Funktionen (oder Klassen TBH) zu überprüfen und nicht zu versuchen, in einem Prozess oder Tool, das schöne grüne Häkchen zeigt, Kästchen anzukreuzen.
quelle
Ich habe ein Werkzeug dafür gebaut
https://github.com/exussum12/coverageChecker
Verwenden von
Schlägt fehl, wenn weniger als 70% des Diff durch Unit-Tests abgedeckt werden.
Holen Sie sich das Diff durch.
Angenommen, Sie haben vom Master verzweigt und werden wieder zum Master zusammengeführt
Ignorieren Sie das phpunit-Flag im Code, es ist wirklich nur eine Kleeprüfung, damit alles, was Klee ausgeben kann, es verwenden kann.
Wie andere Antworten vorgeschlagen haben, ist es keine gute Idee, dies auf 100% zu setzen
quelle