Für ein gut konzipiertes System, bei dem Unit-Tests die Entwicklung von Anfang an vorangetrieben haben, würde ich sagen, dass 85 % eine recht niedrige Zahl ist. Bei kleinen Klassen, die so konzipiert sind, dass sie testbar sind, sollte es nicht schwer sein, mehr als das abzudecken.
Es ist leicht, diese Frage mit einem Satz wie diesem abzutun:
- Gedeckte Linien sind nicht gleich geprüfte Logik, und man sollte nicht zu viel in den Prozentsatz hineininterpretieren.
Stimmt, aber es gibt einige wichtige Punkte zur Codeabdeckung zu sagen. Meiner Erfahrung nach ist diese Metrik tatsächlich recht nützlich, wenn sie richtig eingesetzt wird. Abgesehen davon habe ich nicht alle Systeme gesehen, und ich bin sicher, dass es tonnenweise Systeme gibt, bei denen die Analyse der Codeabdeckung kaum einen echten Mehrwert bringt. Der Code kann so unterschiedlich aussehen und der Umfang des verfügbaren Test-Frameworks kann variieren.
Außerdem bezieht sich meine Argumentation hauptsächlich auf recht kurze Testrückkopplungsschleifen. Für das Produkt, das ich entwickle, ist die kürzeste Rückkopplungsschleife recht flexibel und deckt alles ab, von Klassentests bis zur prozessübergreifenden Signalisierung. Das Testen eines lieferbaren Teilprodukts dauert in der Regel 5 Minuten, und bei einer so kurzen Feedbackschleife ist es in der Tat möglich, die Testergebnisse (und insbesondere die hier betrachtete Codeabdeckungsmetrik) zu verwenden, um Commits im Repository abzulehnen oder zu akzeptieren.
Bei der Verwendung der Codeabdeckungsmetrik sollten Sie nicht nur einen festen (willkürlichen) Prozentsatz vorgeben, der erfüllt werden muss. Meiner Meinung nach bietet dies nicht die wirklichen Vorteile der Codeabdeckungsanalyse. Definieren Sie stattdessen die folgenden Metriken:
- Low Water Mark (LWM), die niedrigste Anzahl unbedeckter Linien, die jemals im geprüften System beobachtet wurde
- High Water Mark (HWM), der höchste Prozentsatz an Codeabdeckung, der jemals für das zu testende System erreicht wurde
Neuer Code kann nur hinzugefügt werden, wenn wir nicht über die LWM und nicht unter die HWM gehen. Mit anderen Worten, die Codeabdeckung ist darf nicht abnehmen und der neue Code sollte abgedeckt sein. Beachten Sie, dass ich "sollte" und nicht "muss" sage (siehe unten).
Aber bedeutet das nicht, dass es unmöglich ist, alten, gut getesteten Müll zu entsorgen, für den man keine Verwendung mehr hat? Ja, und deshalb muss man in diesen Dingen pragmatisch sein. Es gibt Situationen, in denen die Regeln gebrochen werden müssen, aber für Ihre typische alltägliche Integration sind diese Metriken meiner Erfahrung nach recht nützlich. Daraus ergeben sich die folgenden zwei Implikationen.
-
Testbarer Code wird gefördert. Wenn Sie neuen Code hinzufügen, müssen Sie sich wirklich bemühen, den Code testbar zu machen, da Sie versuchen müssen, den gesamten Code mit Ihren Testfällen abzudecken. Testbarer Code ist normalerweise eine gute Sache.
-
Die Testabdeckung für Legacy-Code nimmt mit der Zeit zu. Wenn man neuen Code hinzufügt und nicht in der Lage ist, ihn mit einem Testfall abzudecken, kann man stattdessen versuchen, einen Teil des alten Codes abzudecken, um die LWM-Regel zu umgehen. Diese manchmal notwendige Schummelei hat zumindest den positiven Nebeneffekt, dass die Abdeckung des Legacy-Codes mit der Zeit zunimmt, was die scheinbar strenge Durchsetzung dieser Regeln in der Praxis recht pragmatisch macht.
Und noch einmal: Wenn die Rückkopplungsschleife zu lang ist, könnte es völlig unpraktisch sein, so etwas im Integrationsprozess einzurichten.
Ich möchte noch zwei weitere allgemeine Vorteile der Codeabdeckungsmetrik erwähnen.
-
Die Code-Abdeckungsanalyse ist Teil der dynamischen Code-Analyse (im Gegensatz zur statischen Analyse, z. B. Lint). Probleme, die während der dynamischen Code-Analyse gefunden werden (durch Werkzeuge wie die purify-Familie, http://www-03.ibm.com/software/products/en/rational-purify-family ) sind Dinge wie uninitialisierte Speicherlesevorgänge (UMR), Speicherlecks, usw. Diese Probleme können nur gefunden werden, wenn der Code durch einen ausgeführten Testfall abgedeckt ist . Der Code, der am schwierigsten in einem Testfall abzudecken ist, sind in der Regel die abnormalen Fälle im System, aber wenn Sie wollen, dass das System anständig versagt (d.h. Fehlersuche statt Absturz), sollten Sie sich auch etwas Mühe geben, die abnormalen Fälle in der dynamischen Codeanalyse abzudecken. Mit ein wenig Pech kann eine UMR zu einem Segfault oder Schlimmerem führen.
-
Die Leute sind stolz darauf, dass sie 100 % des neuen Codes einhalten, und die Leute diskutieren Testprobleme mit einer ähnlichen Leidenschaft wie andere Implementierungsprobleme. Wie kann diese Funktion auf eine besser testbare Weise geschrieben werden? Wie würden Sie versuchen, diesen abnormalen Fall abzudecken, usw.
Und ein Negativ, der Vollständigkeit halber.
- In einem großen Projekt mit vielen beteiligten Entwicklern wird sicher nicht jeder ein Testgenie sein. Manche Leute neigen dazu, die Codeabdeckungsmetrik als Beweis dafür zu verwenden, dass der Code getestet ist, was jedoch weit von der Wahrheit entfernt ist. wie in vielen anderen Antworten auf diese Frage erwähnt. Es ist EINE Metrik, die bei richtiger Anwendung einige nette Vorteile bringen kann, aber wenn sie missbraucht wird, kann sie in der Tat zu schlechten Tests führen. Abgesehen von den oben erwähnten sehr wertvollen Nebeneffekten zeigt eine abgedeckte Zeile nur, dass das zu testende System diese Zeile für einige Eingabedaten erreichen kann und dass es ausgeführt werden kann, ohne zu hängen oder abzustürzen.
0 Stimmen
Heutzutage verfügen viele IDEs über Abdeckungshervorhebung. Stellen Sie sicher, dass Sie zumindest die wichtigsten Teile des Codes abdecken, als dass Sie daran denken, einen bestimmten Prozentsatz zu erreichen.
0 Stimmen
Unit-Tests können per Definition einzelne Methoden, ganze Klassen oder ganze Module sein. Selbst wenn Sie alle Methoden testen, testen Sie möglicherweise nicht alle Pfade oder alle Kombinationen, auf die ein Benutzer stößt. Mit Anweisungs- und Verzweigungsabdeckung und MCDCs wird die Situation noch komplexer.
0 Stimmen
Warum wird diese Frage nicht gelöscht oder ordnungsgemäß bearbeitet? Sie hat so viel Interesse geweckt, aber sie ist völlig irreführend.
0 Stimmen
Eine 100%ige Deckung ist das Minimum. Ich möchte wissen, ob ein Punk ein unerwartetes process.exit(1) eingeführt oder aus Spaß oder Unwissenheit irgendwo hingeworfen hat. Wenn man nicht jede Codezeile in einem Build ausführt, werde ich es einfach nicht wissen, bis dieser Code vielleicht irgendwann in der Produktion verwendet wird.
0 Stimmen
Ich denke, dass man sich das besser umgekehrt vorstellt. Die Codeabdeckung sagt sehr wenig aus, außer dass der Code ausgeführt wurde. LACK der Codeabdeckung andererseits bedeutet, dass der Code NIE ausgeführt wurde. Anstatt also eine hohe Codeabdeckung anzustreben, sollten wir vielleicht eher versuchen, so wenig ungetesteten Code wie möglich zu haben. (Der Grund für diese Unterscheidung ist, dass ausgeführter Code nicht unbedingt getesteter Code ist, aber nicht ausgeführter Code ist definitiv ungetesteter Code. IE: abgedeckter Code sollte nicht so sehr geschätzt werden, wie unabgedeckter Code vermieden werden sollte.)