TL; DR
Gute, nützliche Tests zu schreiben ist schwierig und mit hohen Kosten in C ++ verbunden. Können Sie erfahrenen Entwicklern Ihre Überlegungen mitteilen, was und wann zu testen ist?
Lange Geschichte
Früher habe ich testgetrieben entwickelt, mein gesamtes Team, aber es hat bei uns nicht gut funktioniert. Wir haben viele Tests, aber sie scheinen nie die Fälle abzudecken, in denen wir tatsächliche Fehler und Rückschritte haben - die normalerweise auftreten, wenn Einheiten interagieren, und nicht aufgrund ihres isolierten Verhaltens.
Dies ist auf Geräteebene oft so schwierig zu testen, dass wir TDD eingestellt haben (mit Ausnahme von Komponenten, bei denen die Entwicklung wirklich beschleunigt wird) und stattdessen mehr Zeit investiert haben, um die Abdeckung der Integrationstests zu erhöhen. Während die kleinen Unit-Tests keine wirklichen Fehler auffingen und im Grunde nur Wartungsaufwand waren, haben sich die Integrationstests wirklich gelohnt.
Jetzt habe ich ein neues Projekt geerbt und frage mich, wie ich es testen soll. Da es sich um eine native C ++ / OpenGL-Anwendung handelt, kommen Integrationstests nicht in Frage. Unit-Tests in C ++ sind jedoch etwas schwieriger als in Java (Sie müssen explizit Dinge erstellen virtual
), und das Programm ist nicht stark objektorientiert, sodass ich einige Dinge nicht verspotten oder wegstupsen kann.
Ich möchte das Ganze nicht auseinandernehmen und nur ein paar Tests schreiben, um Tests schreiben zu können. Also frage ich dich: Wofür soll ich Tests schreiben? z.B:
- Funktionen / Klassen, die sich voraussichtlich häufig ändern?
- Funktionen / Klassen, die schwieriger manuell zu testen sind?
- Funktionen / Klassen, die bereits leicht zu testen sind?
Ich fing an, einige respektvolle C ++ - Codebasen zu untersuchen, um zu sehen, wie sie getestet werden. Im Moment befasse ich mich mit dem Chromium-Quellcode, aber es fällt mir schwer, die Testgründe aus dem Code zu extrahieren. Wenn jemand ein gutes Beispiel oder einen guten Beitrag dazu hat, wie beliebte C ++ - Benutzer (Leute vom Komitee, Buchautoren, Google, Facebook, Microsoft, ...) dies angehen, wäre das besonders hilfreich.
Aktualisieren
Ich habe mich auf dieser Site und im Web umgesehen, seit ich das geschrieben habe. Einige gute Sachen gefunden:
- Wann ist es angebracht, keinen Komponententest durchzuführen?
- /programming/109432/what-not-to-test-when-it-comes-to-unit-testing
- http://junit.sourceforge.net/doc/faq/faq.htm#best
Leider sind alle eher Java / C # -zentriert. Das Schreiben vieler Tests in Java / C # ist kein großes Problem, daher überwiegt der Nutzen in der Regel die Kosten.
Aber wie ich oben geschrieben habe, ist es schwieriger in C ++. Besonders wenn Ihre Codebasis nicht so gut ist, müssen Sie die Dinge ernsthaft durcheinander bringen, um eine gute Abdeckung durch Unit-Tests zu erhalten. Zum Beispiel: Die von mir geerbte Anwendung hat einen Graphics
Namensraum, der eine dünne Schicht über OpenGL ist. Um eine der Entitäten zu testen, die alle ihre Funktionen direkt verwenden, müsste ich diese in eine Schnittstelle und eine Klasse umwandeln und in alle Entitäten einfügen. Das ist nur ein Beispiel.
Denken Sie bei der Beantwortung dieser Frage bitte daran, dass ich für das Schreiben von Tests ziemlich viel Geld investieren muss.
quelle
Antworten:
Unit Testing ist nur ein Teil. Integrationstests helfen Ihnen bei den Problemen Ihres Teams. Integrationstests können für alle Arten von Anwendungen geschrieben werden, auch für native und OpenGL-Anwendungen. Sie sollten sich "Growing Object Oriented Software Guided by Tests" von Steve Freemann und Nat Pryce ansehen (z . B. http://www.amazon.com/Growing-Object-Oriented-Software-Guided-Signature/dp/0321503627 ). Es führt Sie Schritt für Schritt durch die Entwicklung einer Anwendung mit GUI und Netzwerkkommunikation.
Testen von Software, die nicht getestet wurde, ist eine andere Geschichte. Überprüfen Sie Michael Feathers "Effektiv mit Legacy-Code arbeiten" (http://www.amazon.com/Working-Effective-Legacy-Michael-Feathers/dp/0131177052).
quelle
Es ist eine Schande, TDD "hat nicht gut für Sie funktioniert." Ich denke, das ist der Schlüssel zum Verständnis, wohin man sich wenden muss. Sehen Sie sich noch einmal an und verstehen Sie, warum TDD nicht funktioniert hat, was Sie besser hätten machen können und warum es Schwierigkeiten gab.
Natürlich haben Ihre Unit-Tests die gefundenen Bugs nicht gefunden. Das ist genau der Punkt. :-) Sie haben diese Fehler nicht gefunden, weil Sie sie von vornherein verhindert haben, indem Sie darüber nachgedacht haben, wie die Schnittstellen funktionieren sollten und wie sichergestellt werden kann, dass sie ordnungsgemäß getestet wurden.
Wie Sie festgestellt haben, ist es schwierig, einen Unit-Test-Code zu beantworten, der nicht für den Test vorgesehen ist. Für vorhandenen Code ist es möglicherweise effektiver, eine Funktions- oder Integrationstestumgebung als eine Komponententestumgebung zu verwenden. Testen Sie das System insgesamt und konzentrieren Sie sich dabei auf bestimmte Bereiche.
Natürlich wird die Neuentwicklung von TDD profitieren. Wenn neue Funktionen hinzugefügt werden, kann das Refactoring für TDD dazu beitragen, die neue Entwicklung zu testen und gleichzeitig die Entwicklung eines neuen Komponententests für die älteren Funktionen zu ermöglichen.
quelle
Ich habe TDD in C ++ noch nicht durchgeführt, daher kann ich das nicht kommentieren, aber Sie sollten das erwartete Verhalten Ihres Codes testen. Während sich die Implementierung ändern kann, sollte das Verhalten (normalerweise?) Gleich bleiben. In Java \ C # -zentrierten Umgebungen bedeutet dies, dass Sie nur die öffentlichen Methoden testen, Tests für das erwartete Verhalten schreiben und dies vor der Implementierung tun (was normalerweise besser gesagt als getan ist :)).
quelle