Unit Testing unter C++ (Win32, MSVC)
- Top-OR
- Establishment
- Beiträge: 330
- Registriert: 02.03.2011, 16:32
- Echter Name: Jens H.
- Wohnort: Esslingen/Dessau
- Kontaktdaten:
Unit Testing unter C++ (Win32, MSVC)
Moin ZFXler!
Da der Parallelthread zu Continuous Integration und Cross-Compilation mir ein paar gute Denkanstösse und nen kurz und knackigen Rundumblick gegeben hat (danke soweit allen dafür; der Thread ist weiter für alle Arten von Erfahrungsberichten und Meinungen offen), wage ich mal den Versuch, euch nochmal zu einem dazu artverwandten Thema zu befragen:
Unit-Testing!
Wie gesagt .. mir geht es um meine private C++ Welt und ich will mal bei euch abklopfen, wie eure Ansichten und Erfahrungen zu diesem Thema in C++ sind.
Beruflich bin ich in der Java-Welt mit OSS im Konzernumfeld unterwegs. Im aktuellen Projekt arbeite ich mit einem Kollegen zusammen, der seit ein paar Monaten TDD und Unit-Testing für sich entdeckt hat und das bei uns im aktuellen Projekt umsetzt.
Mann muss dazu sagen, dass hier in meinem Arbeitsumfeld die Leute fast nur Java-Bahnen denken. Das ist manchmal sehr sehr belastend, weil mir persönlich die technische Vielfalt fehlt: Wenn man einen Java-Hammer in der Hand hat, sieht jedes Problem wie ein Java-Nagel aus…. Ihr wisst schon: 4 Jahre Berufserfahrung, Senior Developer und Software-Architect, und nur Java und artverwandte (Web-)Technologien benutzt undn bissel "Angst" .. ähm ... "sachliche Argumente" gegen "neue" Nicht-Java-Technologien" in unserem Kontext. Naja, egal .. will nicht jammern .. das wäre eher was für den Jammer-Thread.
Ich selbst mache die Unit-Tests für meinen Java-Krams auf der Arbeit auch, allerdings nicht mit solcher Begeisterung, wie er, weil mir .. zugegeben … die Benutzung dieser Skills für mein privates Baby (noch) nicht erschließt.
Macht jemand von euch sinnvoll Unit-Testing in C++?
Der Grundgedanke von TDD und Unit-Testing an sich ist auch ganz gut. Da gibt es ja einen Haufen Aspekte, die ich hier garnicht aufzählen kann und möchte.
Allerdings sehe ich bei C++ Schwierigkeiten. In den „interpretierten“ Sprachen (An die Erbsenzähler: jajaja, nicht interpretiert sonder "kompiliert" in Bytecode, ich weiß .. welcher wieder interpretiert wird. *hust*) geht ja das Testen meiner Meinung nach deutlich Besser.
Durch Mechanismen wie Reflections kann der Code ja auch zur Laufzeit Informationen über sich selbst erhalten (Klassenstructuren, etc.). Sowas ist doch nötig, um Objekte zu Isolieren und die Umgebung zu mocken, oder?
In C++ wird’s da ja meiner Meinung nach schwieriger mit den Informationen über „sich selbst“. Wie läuft das in C++?
Wie gut sind die Test- und Mocking-Frameworks für C++? Wie funktioniert Mocking von Klassenmembern, die keine Pointer oder Referenzen sind – geht es überhaupt?
Wie ist eure Meinung zu Unit-Testing: Nicht mehr wegzudenken, sinnvoll, unter Umständen sinnvoll oder totale Zeitverschwendung?
Also ich sehs, mit gewissen Augenmaß gesehen, immernoch als sinnvoll an, allerdings tue ich mich schwer, den echten, meßbanren Benefit zu benennen. Viele von dean angepriesenen Vorteilen sehe ich noch nicht so greifen.. :-/
Besondern ich C++ stehe ich aber, was die Technik angeht, wie die Kuh vorm neuen Tor.
So .. jetzt ihr:
Was sagt ihr zu C++ mit Unit Testing (gerne auch unter dem Aspekt TDD)?
Da der Parallelthread zu Continuous Integration und Cross-Compilation mir ein paar gute Denkanstösse und nen kurz und knackigen Rundumblick gegeben hat (danke soweit allen dafür; der Thread ist weiter für alle Arten von Erfahrungsberichten und Meinungen offen), wage ich mal den Versuch, euch nochmal zu einem dazu artverwandten Thema zu befragen:
Unit-Testing!
Wie gesagt .. mir geht es um meine private C++ Welt und ich will mal bei euch abklopfen, wie eure Ansichten und Erfahrungen zu diesem Thema in C++ sind.
Beruflich bin ich in der Java-Welt mit OSS im Konzernumfeld unterwegs. Im aktuellen Projekt arbeite ich mit einem Kollegen zusammen, der seit ein paar Monaten TDD und Unit-Testing für sich entdeckt hat und das bei uns im aktuellen Projekt umsetzt.
Mann muss dazu sagen, dass hier in meinem Arbeitsumfeld die Leute fast nur Java-Bahnen denken. Das ist manchmal sehr sehr belastend, weil mir persönlich die technische Vielfalt fehlt: Wenn man einen Java-Hammer in der Hand hat, sieht jedes Problem wie ein Java-Nagel aus…. Ihr wisst schon: 4 Jahre Berufserfahrung, Senior Developer und Software-Architect, und nur Java und artverwandte (Web-)Technologien benutzt undn bissel "Angst" .. ähm ... "sachliche Argumente" gegen "neue" Nicht-Java-Technologien" in unserem Kontext. Naja, egal .. will nicht jammern .. das wäre eher was für den Jammer-Thread.
Ich selbst mache die Unit-Tests für meinen Java-Krams auf der Arbeit auch, allerdings nicht mit solcher Begeisterung, wie er, weil mir .. zugegeben … die Benutzung dieser Skills für mein privates Baby (noch) nicht erschließt.
Macht jemand von euch sinnvoll Unit-Testing in C++?
Der Grundgedanke von TDD und Unit-Testing an sich ist auch ganz gut. Da gibt es ja einen Haufen Aspekte, die ich hier garnicht aufzählen kann und möchte.
Allerdings sehe ich bei C++ Schwierigkeiten. In den „interpretierten“ Sprachen (An die Erbsenzähler: jajaja, nicht interpretiert sonder "kompiliert" in Bytecode, ich weiß .. welcher wieder interpretiert wird. *hust*) geht ja das Testen meiner Meinung nach deutlich Besser.
Durch Mechanismen wie Reflections kann der Code ja auch zur Laufzeit Informationen über sich selbst erhalten (Klassenstructuren, etc.). Sowas ist doch nötig, um Objekte zu Isolieren und die Umgebung zu mocken, oder?
In C++ wird’s da ja meiner Meinung nach schwieriger mit den Informationen über „sich selbst“. Wie läuft das in C++?
Wie gut sind die Test- und Mocking-Frameworks für C++? Wie funktioniert Mocking von Klassenmembern, die keine Pointer oder Referenzen sind – geht es überhaupt?
Wie ist eure Meinung zu Unit-Testing: Nicht mehr wegzudenken, sinnvoll, unter Umständen sinnvoll oder totale Zeitverschwendung?
Also ich sehs, mit gewissen Augenmaß gesehen, immernoch als sinnvoll an, allerdings tue ich mich schwer, den echten, meßbanren Benefit zu benennen. Viele von dean angepriesenen Vorteilen sehe ich noch nicht so greifen.. :-/
Besondern ich C++ stehe ich aber, was die Technik angeht, wie die Kuh vorm neuen Tor.
So .. jetzt ihr:
Was sagt ihr zu C++ mit Unit Testing (gerne auch unter dem Aspekt TDD)?
--
Verallgemeinerungen sind IMMER falsch.
Verallgemeinerungen sind IMMER falsch.
- Schrompf
- Moderator
- Beiträge: 5047
- Registriert: 25.02.2009, 23:44
- Benutzertext: Lernt nur selten dazu
- Echter Name: Thomas
- Wohnort: Dresden
- Kontaktdaten:
Re: Unit Testing unter C++ (Win32, MSVC)
Ich habe seit Ewigkeiten vor, aber noch nicht umgesetzt, ein Rudel Unit Tests für meine grundlegenden Klassen zu schreiben. Das werde ich dann spätestens beim Voxelprojekt auch tun, weil es da ne Menge komplexer Logik gibt, die am Ende reproduzierbar Bitfolgen ausspucken soll. Und ich denke, auf so einem basalen Niveau ist UT auf jeden Fall ne gute Sache.
Darüber hinausgehend beginnen bei mir allerdings die Zweifel, zumindest im Kontext der privaten Spielebastelei. Wenn ich für Alles erst Unit Tests schreiben müsste, würde ich ne Menge Spiellogik wahrscheinlich nie schreiben. TDD erscheint mir persönlich als zuviel.
Darüber hinausgehend beginnen bei mir allerdings die Zweifel, zumindest im Kontext der privaten Spielebastelei. Wenn ich für Alles erst Unit Tests schreiben müsste, würde ich ne Menge Spiellogik wahrscheinlich nie schreiben. TDD erscheint mir persönlich als zuviel.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
- Krishty
- Establishment
- Beiträge: 8316
- Registriert: 26.02.2009, 11:18
- Benutzertext: state is the enemy
- Kontaktdaten:
Re: Unit Testing unter C++ (Win32, MSVC)
Du musst den Nutzen (weniger Zeit mit Debugging verschwenden) gegen die Kosten (mehr Zeit mit dem Schreiben von Tests verschwenden) abwägen. Und der erste Faktor hängt von der Größe des Projekts ab:
Ich kann aber schnell einen Testfall „Benutzer steuert bei 5 km/h nach links und nach vier Sekunden ist das Fahrzeug um 90° gedreht und hat 8 m zurückgelegt“ manuell durchführen, mit dem hundert Funktionen auf einmal überprüft werden und an dem ich schnell merke, wenn ich was kaputtgemacht habe.
Aber auch nur, so lange die selbe Funktion nicht gleichzeitig für Spezialfälle bei GPU-Fluidsimulation eingesetzt wird, die ich unmöglich manuell erzeugen und überprüfen kann. Und damit wären wir wieder bei der Komplexität.
- Tausend Zeilen Quelltext -> wenig Komplexität -> einfach einbauen und gucken, ob das Programm noch läuft
- Millionen Zeilen Quelltext -> viel Komplexität -> Unit Tests (weil du manuell gar nicht alle Fälle durchtesten könntest, in denen durch die Änderung was kaputtgehen kann)
- Tausend Zeilen, von denen aber 900 andere Leute geschrieben haben, von denen du nicht weißt, wie sie ticken -> Unit Tests (weil du nicht darauf kommen würdest, für was die deine Funktionen missbraucht haben und was alles kaputtgeht, wenn du was änderst)
Ich kann aber schnell einen Testfall „Benutzer steuert bei 5 km/h nach links und nach vier Sekunden ist das Fahrzeug um 90° gedreht und hat 8 m zurückgelegt“ manuell durchführen, mit dem hundert Funktionen auf einmal überprüft werden und an dem ich schnell merke, wenn ich was kaputtgemacht habe.
Aber auch nur, so lange die selbe Funktion nicht gleichzeitig für Spezialfälle bei GPU-Fluidsimulation eingesetzt wird, die ich unmöglich manuell erzeugen und überprüfen kann. Und damit wären wir wieder bei der Komplexität.
- Top-OR
- Establishment
- Beiträge: 330
- Registriert: 02.03.2011, 16:32
- Echter Name: Jens H.
- Wohnort: Esslingen/Dessau
- Kontaktdaten:
Re: Unit Testing unter C++ (Win32, MSVC)
Hmm .. ich kann so 100% auch nicht an Unit-Testing und TDD als Allheilmittel der Qualitätsicherungs glauben. So ist es auch explizit nicht gedacht.
Es ist, wie immer, eine Sache des Augemaßes, wann man das anwendet.
Aber wenn ich von manchen Jungs Kommentare höre wie "Durch Unit-Testing haben wir ein sehr bequemes Auffangnetz für Fehler und können nach Herzenlust refractoren und können uns [Einhundert Prozent (so zumindest der Subtext, den ich da lese)] sicher sein, NICHTS (!) kaputt gemacht zu haben.", bekomme ich meine Zweifel, ob mancher vielleicht Unittesting zu stark überbewertet. Da sind übrigens in meiner Wahnehmung Menschen, die in ihrer Freizeit NICHT(!) programmieren, sondern nur beruflich die im "Lehrbuch für Clean Code" und auf 2-Tages-Schulungen aufgefangene Begeisterung (vielleicht auch durch einen guten Coach bedingt) an ihrem beruflichem Umfeld ausprobieren.
Ein Contra ist auch die trügerische Sicherheit, in der man sich wägt.
Es ist eine sehr schwer zu messende Thematik. In meinen Augen fast schon mit religiösen Zügen und esoterischen Aspekten. Deswegen möchte ich gerne auch mal echte (!) Erfahrungswerte hier abklopfen. Mehr als das übliche: "Also in meinem letzten Projekt hat Unit-Testing uns geholfen, X Fehler zu finden! - ich finde es subjektiv gut."
Wie Krishty andeutet: algorithmische/mathematische Probleme zu orten, ist damit sicher nicht so leicht. Auch ich halte Unit-Testing da für das falsche Werkzeug.
Es ist in meinen Augen eher gut, um strukturelle Probleme zu orten und frühzeitig zu entdecken.
Mal von der Sperrigkeit, die ja in gewisser Weise gewollt ist, mal abgesehen. (Aber auch da stimme ich dir zu!)
Und, es ist immer ein Tradeoff zwischen Kosten und Nutzen, den die Evangelisten von UT in meinen Augen auch manchmal zu Gunsten der Tests verkaufen.
Oder? Weiter Senf hierzu? Ich bitte darum...
Ich versuche mir gerade wirklich, ein nicht zu emotional verzerrtes Bild zu machen und, wie gesagt, den Nutzen für mich und meine C++-Welt in einem "mittelgroßen" (was auch immer DAS bedeutet) Projekt abzuwägen.
Es ist, wie immer, eine Sache des Augemaßes, wann man das anwendet.
Aber wenn ich von manchen Jungs Kommentare höre wie "Durch Unit-Testing haben wir ein sehr bequemes Auffangnetz für Fehler und können nach Herzenlust refractoren und können uns [Einhundert Prozent (so zumindest der Subtext, den ich da lese)] sicher sein, NICHTS (!) kaputt gemacht zu haben.", bekomme ich meine Zweifel, ob mancher vielleicht Unittesting zu stark überbewertet. Da sind übrigens in meiner Wahnehmung Menschen, die in ihrer Freizeit NICHT(!) programmieren, sondern nur beruflich die im "Lehrbuch für Clean Code" und auf 2-Tages-Schulungen aufgefangene Begeisterung (vielleicht auch durch einen guten Coach bedingt) an ihrem beruflichem Umfeld ausprobieren.
Ein Contra ist auch die trügerische Sicherheit, in der man sich wägt.
Es ist eine sehr schwer zu messende Thematik. In meinen Augen fast schon mit religiösen Zügen und esoterischen Aspekten. Deswegen möchte ich gerne auch mal echte (!) Erfahrungswerte hier abklopfen. Mehr als das übliche: "Also in meinem letzten Projekt hat Unit-Testing uns geholfen, X Fehler zu finden! - ich finde es subjektiv gut."
Wie Krishty andeutet: algorithmische/mathematische Probleme zu orten, ist damit sicher nicht so leicht. Auch ich halte Unit-Testing da für das falsche Werkzeug.
Es ist in meinen Augen eher gut, um strukturelle Probleme zu orten und frühzeitig zu entdecken.
Mal von der Sperrigkeit, die ja in gewisser Weise gewollt ist, mal abgesehen. (Aber auch da stimme ich dir zu!)
Und, es ist immer ein Tradeoff zwischen Kosten und Nutzen, den die Evangelisten von UT in meinen Augen auch manchmal zu Gunsten der Tests verkaufen.
Oder? Weiter Senf hierzu? Ich bitte darum...
Ich versuche mir gerade wirklich, ein nicht zu emotional verzerrtes Bild zu machen und, wie gesagt, den Nutzen für mich und meine C++-Welt in einem "mittelgroßen" (was auch immer DAS bedeutet) Projekt abzuwägen.
--
Verallgemeinerungen sind IMMER falsch.
Verallgemeinerungen sind IMMER falsch.
Re: Unit Testing unter C++ (Win32, MSVC)
Also ich sehe das eigentlich genauso wie die anderen auch.
Managern kann man die Tests halt gut verkaufen, je später ein Fehler auffällt, desto teurer wird er. Und da Unit Test relativ früh im Geschäftsprozess ansetzen, spart man dadurch also theoretisch Geld.
Nur das Problem ist, dass man ja (meistens) nicht für alles Tests schreiben kann. D.h. man hat einen gewissen Rahmen, in dem die Software definitiv funktioniert, nicht mehr aber auch nicht weniger.
Spannend wird es natürlich vor allem dann, wenn eine Software aus verschiedenen Modulen besteht die in verschiedenen Projekten wiederverwendet werden, ggf. auch von anderen Leuten.
Dann hat man ja gar keine andere Möglichkeit, als innerhalb eines Teams sein eigenes Modul zu testen und das wars. Alle weiteren Probleme fallen dann halt bei Integrations-Tests auf.
Weiterhin solltest du beachten, dass du ja auch die Tests bei Änderungen immer mit anpassen musst.
Worüber du dir Gedanken machen kannst ist also:
* Wieviele Module hast du?
* Wie oft werden die wiederverwendet?
* Welche Sachen müssen als Unit Test laufen, weil sie z.B. sonst garnicht verwendet/getestet werden?
* Welchen Rahmen willst du testen?
Ein Beispiel was mir dazu immer einfällt ist SQLite; sie behaupten 100% branch coverage zu haben (habs nicht nachgeschaut :-)): http://www.sqlite.org/testing.html
Für das Projekt ist sowas aber auch sinnvoll, weil sie ja nicht wissen was andere mit der Library so alles anstellen.
Außerdem ist sowas verdammt viel Aufwand: jedes if und jedes else müssen durchlaufen werden, jeder Loop 0,1, und >1 mal, uvm.
Und bei jeder Code-Änderung passt du mindestens nochmal soviele Unit-Tests an.
PS: Der Wikipedia-Artikel dazu ist interessanterweise auch echt gut: http://de.wikipedia.org/wiki/Modultest
Managern kann man die Tests halt gut verkaufen, je später ein Fehler auffällt, desto teurer wird er. Und da Unit Test relativ früh im Geschäftsprozess ansetzen, spart man dadurch also theoretisch Geld.
Nur das Problem ist, dass man ja (meistens) nicht für alles Tests schreiben kann. D.h. man hat einen gewissen Rahmen, in dem die Software definitiv funktioniert, nicht mehr aber auch nicht weniger.
Spannend wird es natürlich vor allem dann, wenn eine Software aus verschiedenen Modulen besteht die in verschiedenen Projekten wiederverwendet werden, ggf. auch von anderen Leuten.
Dann hat man ja gar keine andere Möglichkeit, als innerhalb eines Teams sein eigenes Modul zu testen und das wars. Alle weiteren Probleme fallen dann halt bei Integrations-Tests auf.
Weiterhin solltest du beachten, dass du ja auch die Tests bei Änderungen immer mit anpassen musst.
Worüber du dir Gedanken machen kannst ist also:
* Wieviele Module hast du?
* Wie oft werden die wiederverwendet?
* Welche Sachen müssen als Unit Test laufen, weil sie z.B. sonst garnicht verwendet/getestet werden?
* Welchen Rahmen willst du testen?
Ein Beispiel was mir dazu immer einfällt ist SQLite; sie behaupten 100% branch coverage zu haben (habs nicht nachgeschaut :-)): http://www.sqlite.org/testing.html
Für das Projekt ist sowas aber auch sinnvoll, weil sie ja nicht wissen was andere mit der Library so alles anstellen.
Außerdem ist sowas verdammt viel Aufwand: jedes if und jedes else müssen durchlaufen werden, jeder Loop 0,1, und >1 mal, uvm.
Und bei jeder Code-Änderung passt du mindestens nochmal soviele Unit-Tests an.
PS: Der Wikipedia-Artikel dazu ist interessanterweise auch echt gut: http://de.wikipedia.org/wiki/Modultest
Re: Unit Testing unter C++ (Win32, MSVC)
Nachdem ich mal einiges gutes über Unit-Testing gehört habe, hab ich mich auch mal ein wenig damit beschäftigt, aber nie wirklich ausführlich. Wenn ich mich recht erinnere, gab es aber für C++ Bibliotheken die sehr einfach zu benutzen schienen, so dass man nicht massig overhead hat, sondern wirklich fast nur die Testlogik implementieren muss.
Für meine Projekte (=> Spiele) habe ich aber nicht vor, Unit-Testing einzusetzen. Es erscheint mir doch arg kompliziert, wirklich vernünftige Tests zu schreiben. Wenn man eine handvoll einfacher Funktionen hat, in die man Werte schmeißt, und Werte rausbekommt, kann man mit ein wenig Wissen über die Funktion sehr leicht ganz ordentliche Testfälle konstruieren. Aber in Spielen habe ich typischerweise ein recht komplexes Zusammenspiel diverser Klassen. Wenn Tests recht hoch oben in der Spiellogik ansetzen, testen sie ein komplexes Zusammenspiel von diversen Objekten, was schwer zu initialisieren, schwer zu definieren, war eigentlich passieren soll und unter Umständen auch schwer zu überprüfen, ob eine Bedingung jetzt überhaupt erfüllt ist. Wenn man hingegen tiefer ansetzt, testet man dann irgendwann ob nach dem aufheben eines Gegenstandes dieser auch wirklich im Inventar ist, und so viel traue ich mir dann schon zu.
Ob beispielsweise die Kollisionsabfrage funktioniert oder die KI sich so verhält, wie ich möchte, kann man im Spiel sehr sehr schnell sehen. Tests hingegen wären sehr schwer dafür zu schreiben und man muss die dann ja auch noch warten.
Und zum Thema Code umschreiben: Wenn man robust programmiert, wird halt extrem viel schon beim Kompilieren erkannt. Ich habe es schon einige Male erlebt, dass ich wirklich fundamentale Dinge umgestellt habe, und danach mein Projekt zwei Wochen lang nicht mehr kompiliert werden konnte. Dann habe ich alles umgeschrieben und angepasst, wonach es in der Regel startete, aber dann einfach am Start oder anderen sehr offensichtlichen Stellen direkt abstürzte. Die Fehler waren in der Regel schnell gefunden und beseitigt. Dass ich durch Refaktorn wirklich subtiele Fehler, die schwer zu finden sind und lange Zeit gar nicht auftauchen eingebaut habe, ist mir soweit ich mich erinneren kann nahezu nie passiert. Ich bin bei allen Codeumbauten also auch ohne Unit-Tests eigentlich sehr gut zurecht gekommen. Es ist nie passiert, dass ich irgendwann vor einem total zerschossenen Projekt stand, das unmöglich zu fixen war.
Und die Frage ist dann halt auch, wie viele von meinen Unit-Tests nach meinem Umbau noch kompilieren würden. Und wenn ich dann irgendwann anfange und erst meine Tests umschreiben muss, hat es mir halt auch irgendwie nichts gebracht.
Vielleicht sagt jetzt jemand, meine Programme wären mies geschrieben und die Komponenten einfach viel zu stark voneinander abhängig. Aber nach meinem Gefühl ist gerade das komplexe Zusammenspiel von Klassen ein interessanter Testfall, weil man halt einzelne Funktionen doch in der Regel irgendwie fehlerfrei hinbekommt. Das was ich also testen könnte, ist für mich uninteressant, aber die interessanten Teile erscheinen mir sehr schwer testbar.
Nun, ich glaube auch tatsächlich, dass es von der Programmiersprache abhängig. Ich hatte in Python schon eine Millionen male das Problem, dass mein Programm abgestürzt ist, weil ich Syntaxfehler im Quellcode hatte. Wenn man da irgendwelche Unit-Tests hat, die einfach darauf ausgelegt sind, jeden Codepfad einmal irgendwie zu testen, findet man sowas natürlich sehr schön. Aber nach meinem Empfinden, kann man C++ eben so programmieren, dass der Compiler schon extrem viele Fehler findet. Typsicherheit, const-correctness und nicht zuletzt einfache Syntaxprüfung finden einfach schon unglaublich viel.
Für meine Projekte (=> Spiele) habe ich aber nicht vor, Unit-Testing einzusetzen. Es erscheint mir doch arg kompliziert, wirklich vernünftige Tests zu schreiben. Wenn man eine handvoll einfacher Funktionen hat, in die man Werte schmeißt, und Werte rausbekommt, kann man mit ein wenig Wissen über die Funktion sehr leicht ganz ordentliche Testfälle konstruieren. Aber in Spielen habe ich typischerweise ein recht komplexes Zusammenspiel diverser Klassen. Wenn Tests recht hoch oben in der Spiellogik ansetzen, testen sie ein komplexes Zusammenspiel von diversen Objekten, was schwer zu initialisieren, schwer zu definieren, war eigentlich passieren soll und unter Umständen auch schwer zu überprüfen, ob eine Bedingung jetzt überhaupt erfüllt ist. Wenn man hingegen tiefer ansetzt, testet man dann irgendwann ob nach dem aufheben eines Gegenstandes dieser auch wirklich im Inventar ist, und so viel traue ich mir dann schon zu.
Ob beispielsweise die Kollisionsabfrage funktioniert oder die KI sich so verhält, wie ich möchte, kann man im Spiel sehr sehr schnell sehen. Tests hingegen wären sehr schwer dafür zu schreiben und man muss die dann ja auch noch warten.
Und zum Thema Code umschreiben: Wenn man robust programmiert, wird halt extrem viel schon beim Kompilieren erkannt. Ich habe es schon einige Male erlebt, dass ich wirklich fundamentale Dinge umgestellt habe, und danach mein Projekt zwei Wochen lang nicht mehr kompiliert werden konnte. Dann habe ich alles umgeschrieben und angepasst, wonach es in der Regel startete, aber dann einfach am Start oder anderen sehr offensichtlichen Stellen direkt abstürzte. Die Fehler waren in der Regel schnell gefunden und beseitigt. Dass ich durch Refaktorn wirklich subtiele Fehler, die schwer zu finden sind und lange Zeit gar nicht auftauchen eingebaut habe, ist mir soweit ich mich erinneren kann nahezu nie passiert. Ich bin bei allen Codeumbauten also auch ohne Unit-Tests eigentlich sehr gut zurecht gekommen. Es ist nie passiert, dass ich irgendwann vor einem total zerschossenen Projekt stand, das unmöglich zu fixen war.
Und die Frage ist dann halt auch, wie viele von meinen Unit-Tests nach meinem Umbau noch kompilieren würden. Und wenn ich dann irgendwann anfange und erst meine Tests umschreiben muss, hat es mir halt auch irgendwie nichts gebracht.
Vielleicht sagt jetzt jemand, meine Programme wären mies geschrieben und die Komponenten einfach viel zu stark voneinander abhängig. Aber nach meinem Gefühl ist gerade das komplexe Zusammenspiel von Klassen ein interessanter Testfall, weil man halt einzelne Funktionen doch in der Regel irgendwie fehlerfrei hinbekommt. Das was ich also testen könnte, ist für mich uninteressant, aber die interessanten Teile erscheinen mir sehr schwer testbar.
Nun, ich glaube auch tatsächlich, dass es von der Programmiersprache abhängig. Ich hatte in Python schon eine Millionen male das Problem, dass mein Programm abgestürzt ist, weil ich Syntaxfehler im Quellcode hatte. Wenn man da irgendwelche Unit-Tests hat, die einfach darauf ausgelegt sind, jeden Codepfad einmal irgendwie zu testen, findet man sowas natürlich sehr schön. Aber nach meinem Empfinden, kann man C++ eben so programmieren, dass der Compiler schon extrem viele Fehler findet. Typsicherheit, const-correctness und nicht zuletzt einfache Syntaxprüfung finden einfach schon unglaublich viel.
Lieber dumm fragen, als dumm bleiben!
https://jonathank.de/games/
https://jonathank.de/games/
- Chromanoid
- Moderator
- Beiträge: 4273
- Registriert: 16.10.2002, 19:39
- Echter Name: Christian Kulenkampff
- Wohnort: Lüneburg
Re: Unit Testing unter C++ (Win32, MSVC)
Ich denke auch, dass es da sehr auf das gesunde Maß ankommt. Je größer und langlebiger das Projekt je sinnvoller sind Unittests, Integrationsstests usw. Irgendwann weiß man einfach nicht mehr welche Stelle vielleicht etwas unerwartetere Wege geht und Seiteneffekte werden damit schwer zu überblicken. Unittests geben dann wenigstens schon mal eine gewisse Sicherheit, die man sonst nur durch ein ausgiebiges Code Review und manuelle Tests erhalten würde. Und wenn man einen Bug behebt, kann ein Unittest, der genau diesen Bug prüft, eine Regression verhindern.
Um die Sinnhaftigkeit und Zweckmäßigkeit von Unittests zu erhöhen/prüfem kann man ja z.B. auch noch Mutation testing betreiben, allerdings habe ich das noch nicht ausprobiert, in C++ ist das bestimmt auch noch mal eine Ecke schwieriger als mit "dynamischeren" Sprachen wie Java oder C#.
TDD hat ja auch zum Ziel dem Entwickler von Anfang an dazu zu zwingen seine Anforderungen an die Funktionen klar zu definieren (durch die als erstes zu schreibenden Tests). Diese Perspektive finde ich prinzipiell sinnvoll.
Um die Sinnhaftigkeit und Zweckmäßigkeit von Unittests zu erhöhen/prüfem kann man ja z.B. auch noch Mutation testing betreiben, allerdings habe ich das noch nicht ausprobiert, in C++ ist das bestimmt auch noch mal eine Ecke schwieriger als mit "dynamischeren" Sprachen wie Java oder C#.
TDD hat ja auch zum Ziel dem Entwickler von Anfang an dazu zu zwingen seine Anforderungen an die Funktionen klar zu definieren (durch die als erstes zu schreibenden Tests). Diese Perspektive finde ich prinzipiell sinnvoll.
- Sternmull
- Establishment
- Beiträge: 264
- Registriert: 27.04.2007, 00:30
- Echter Name: Til
- Wohnort: Dresden
Re: Unit Testing unter C++ (Win32, MSVC)
Bei mir auf Arbeit habe ich vor ein paar Jahren Test-Helfer für C++ erstellt um unsere Assertion-basierten Tests in richtige Unit- bzw. Regression-Tests zu verwandeln. Die Assertion-basierten Tests ließen sich halt nur manuell von einem Entwickler mit dem Debug-Build ausführen... und konnten meistens auch nur von dem Autor vernünftig ausgewertet werden (sofern er nicht bereits vergessen hatte was das alles sollte). Mit den Test-Helfern wurden die Assertions durch andere Makros ersetzt die sowohl in Debug- also auch im Release-Build auf die Annahme prüfen und gleichzeitig die Annahme und das Ergebnis in ein Logfile schreiben. Außerdem gibts noch eine Funktion die einfach nur was ins Logfile schreibt. Als zusätzlichen Komfort gibts noch ein Makro um Testfunktionen zu definieren, die registrieren sich dann automatisch in einer Liste der verfügbaren Tests und können von einer generischen Einstiegsfunktion der reihe nach ausgeführt werden.
Der Witz an der Sache ist, dass man das Logfile eines Tests den man ein mal für erfolgreich befunden hat aufheben kann. Dieses Logfile lässt sich dann automatisch mit Logs von späteren Test-Durchläufen vergleichen. Dadurch wird es sehr einfach existierendes Verhalten festzuhalten und anschließend zu testen ob dieses weiterhin beibehalten wird. Das macht sich in der Praxis oft einfacher als explizite Test-Bedingungen zu formulieren (z.B. wird bei einer String-Formatierungs-Funktion einfach getestet ob immer noch die gleiche Ausgabe raus kommt, ohne das man alle Ausgabe-Strings explizit im Quelltext der Test-Funktion zu stehen hat).
Mittlerweile haben sich alle angewöhnt für neue kritische Bibliotheksfunktionen gleich auch Testfunktionen zu schreiben. Das tut nicht weh weil man die ja eh testen und debuggen muss, und die Test-Helfer mittlerweile der einfachste Weg sind das zu tun. Anders herum hab ich mir schon öfters Tests gebaut um das verhalten von altem Code zu protokollieren bevor ich ihn angepasst hab. Und dabei bin ich auch für ganz zentrale und häufig verwendete Funktionalität schon auf die gräulichsten Fehler gestoßen, einfach weil sie noch nie jemand ernsthaft getestet hat sondern immer nur in der Praxis eingesetzt hat wo dann glücklicherweise alles gut ging. Wenn ein Bug ein einer Bibliothek auftritt, dann schreib ich normalerweise auch erst mal einen Test der wegen des Fehlverhaltens anschlägt, und repariere es anschließend. So ist dann auch gleich unmissverständlich festgehalten wie das Problem zu reproduzieren war.
Der Witz an der Sache ist, dass man das Logfile eines Tests den man ein mal für erfolgreich befunden hat aufheben kann. Dieses Logfile lässt sich dann automatisch mit Logs von späteren Test-Durchläufen vergleichen. Dadurch wird es sehr einfach existierendes Verhalten festzuhalten und anschließend zu testen ob dieses weiterhin beibehalten wird. Das macht sich in der Praxis oft einfacher als explizite Test-Bedingungen zu formulieren (z.B. wird bei einer String-Formatierungs-Funktion einfach getestet ob immer noch die gleiche Ausgabe raus kommt, ohne das man alle Ausgabe-Strings explizit im Quelltext der Test-Funktion zu stehen hat).
Mittlerweile haben sich alle angewöhnt für neue kritische Bibliotheksfunktionen gleich auch Testfunktionen zu schreiben. Das tut nicht weh weil man die ja eh testen und debuggen muss, und die Test-Helfer mittlerweile der einfachste Weg sind das zu tun. Anders herum hab ich mir schon öfters Tests gebaut um das verhalten von altem Code zu protokollieren bevor ich ihn angepasst hab. Und dabei bin ich auch für ganz zentrale und häufig verwendete Funktionalität schon auf die gräulichsten Fehler gestoßen, einfach weil sie noch nie jemand ernsthaft getestet hat sondern immer nur in der Praxis eingesetzt hat wo dann glücklicherweise alles gut ging. Wenn ein Bug ein einer Bibliothek auftritt, dann schreib ich normalerweise auch erst mal einen Test der wegen des Fehlverhaltens anschlägt, und repariere es anschließend. So ist dann auch gleich unmissverständlich festgehalten wie das Problem zu reproduzieren war.
- ponx
- Establishment
- Beiträge: 217
- Registriert: 04.05.2008, 12:52
- Echter Name: Andy Ponx
- Wohnort: Hamburg
- Kontaktdaten:
Re: Unit Testing unter C++ (Win32, MSVC)
Ich hab bei der Spiele-Entwicklung auch festgestellt, dass die wirklich schlimmen Fehler eigentlich nie im Model auftreten (wo man ordentliche Tests schreiben könnte), sondern meistens irgendwelche fiesen Engine/Grafik-Geschichten sind, die sich schwer als Test abbilden lassen und/oder sich eh ständig ändern.
Für die Arbeit an unserer Musik-Middleware (seit 5 Jahren in der Entwicklung) sind die Tests allerdings grundsätzlich ein Segen. Man fängt natürlich nie alles ab, aber eben doch das Gröbste.
Ich benutze momentan NUnit, weil ich damit (theoretisch) sowohl die .NET - Implementierung unserer API (in C#), als auch die native (in C++) testen kann. In der Praxis sieht das momentan so aus, dass mir leider ständig NUnit abschmiert (siehe anderer Thread von heute morgen). Wenn mir jemand eine Alternative empfehlen kann, gerne! Ansonsten würde ich jetzt wieder zurück zu GoogleTest, damit war ich immer ganz happy, aber konnte halt nur unter C++ testen.
Für die Arbeit an unserer Musik-Middleware (seit 5 Jahren in der Entwicklung) sind die Tests allerdings grundsätzlich ein Segen. Man fängt natürlich nie alles ab, aber eben doch das Gröbste.
Ich benutze momentan NUnit, weil ich damit (theoretisch) sowohl die .NET - Implementierung unserer API (in C#), als auch die native (in C++) testen kann. In der Praxis sieht das momentan so aus, dass mir leider ständig NUnit abschmiert (siehe anderer Thread von heute morgen). Wenn mir jemand eine Alternative empfehlen kann, gerne! Ansonsten würde ich jetzt wieder zurück zu GoogleTest, damit war ich immer ganz happy, aber konnte halt nur unter C++ testen.
- kimmi
- Moderator
- Beiträge: 1405
- Registriert: 26.02.2009, 09:42
- Echter Name: Kim Kulling
- Wohnort: Luebeck
- Kontaktdaten:
Re: Unit Testing unter C++ (Win32, MSVC)
Zur Frage brauchbarer UnitTest-Frameworks: catch + googletest ( dies besonders mit google-mock ).
Zu Unittests:
Wenn man ein Hobby-Projekt betreibt, macht es nicht immer Sinn, Unittests für alles zu schreiben. Wenn ich einen Bugreport von außerhalt bekomme, versuche ich den gerne mittels eines Unittests nachzustellen und löse ihn dann. Das setzt voraus, dass der Code per Unittest getestet werden kann. Unittest per so sollen genau eine Klasse / Module / Interface auf Zuverlässigkeit testen. Wenn man nebenbei noch die Datenbank hochfahren muss, den OpenGLRenderer benötigt und 2 Modelle laden muss, so ist das kein Unittest. Es handelt sich um einen Integrationstest, da ja die Integration mehrerer Klassen im Zusammenspiel getestet wird.
Wenn sich die Klasse aufgrund von offensichtlicher oder versteckter Dependencies nicht alleine für einen Unittest instantisieren lässt, ist das meiner Erfahrung nach auch kein besonders gutes Zeichen für die dahinterliegende Architektur bzw. das Klassendesign.
Wenn man per se sagt, dass Unittests nicht so viel Sinn machen, kann sich gerne mal wie ich hier mit dem Haufen von Legacy-Produkten ohne jegliche Form automatisierter Tests herumschlagen. Automatisierte Tests stellen nicht nur ein Sicherheitsnetz dar, sie dokumentieren auch die wirklichen Usecases für die API's. Und wenn man bei einem 20-Jahre alten Produkt mit Gammeltechnik und veralteter Doku und Requirements ein neues Feature einbauen darf, freut man sich über so etwas ungemein. Und Gerüchte besagen, dass mancher seinen 1 Jahre alten Code auch schon mal nicht mehr verstanden hat ( mir ist das schon passiert ) ;).
Wir testen auch unsere UI automatisiert und diese Tests helfen beim Debuggen ungemein. Allerdings machen wir auch jede Menge explorative Tests, da sich nicht alles per automatisiertem Test bzw. Unittest finden lässt. Allerdings haben wir hier auch andere Anforderungen an Verifikation und Testabdeckung als in einem Hobby-Projekt.
Gruß Kimmi
Zu Unittests:
Wenn man ein Hobby-Projekt betreibt, macht es nicht immer Sinn, Unittests für alles zu schreiben. Wenn ich einen Bugreport von außerhalt bekomme, versuche ich den gerne mittels eines Unittests nachzustellen und löse ihn dann. Das setzt voraus, dass der Code per Unittest getestet werden kann. Unittest per so sollen genau eine Klasse / Module / Interface auf Zuverlässigkeit testen. Wenn man nebenbei noch die Datenbank hochfahren muss, den OpenGLRenderer benötigt und 2 Modelle laden muss, so ist das kein Unittest. Es handelt sich um einen Integrationstest, da ja die Integration mehrerer Klassen im Zusammenspiel getestet wird.
Wenn sich die Klasse aufgrund von offensichtlicher oder versteckter Dependencies nicht alleine für einen Unittest instantisieren lässt, ist das meiner Erfahrung nach auch kein besonders gutes Zeichen für die dahinterliegende Architektur bzw. das Klassendesign.
Wenn man per se sagt, dass Unittests nicht so viel Sinn machen, kann sich gerne mal wie ich hier mit dem Haufen von Legacy-Produkten ohne jegliche Form automatisierter Tests herumschlagen. Automatisierte Tests stellen nicht nur ein Sicherheitsnetz dar, sie dokumentieren auch die wirklichen Usecases für die API's. Und wenn man bei einem 20-Jahre alten Produkt mit Gammeltechnik und veralteter Doku und Requirements ein neues Feature einbauen darf, freut man sich über so etwas ungemein. Und Gerüchte besagen, dass mancher seinen 1 Jahre alten Code auch schon mal nicht mehr verstanden hat ( mir ist das schon passiert ) ;).
Wir testen auch unsere UI automatisiert und diese Tests helfen beim Debuggen ungemein. Allerdings machen wir auch jede Menge explorative Tests, da sich nicht alles per automatisiertem Test bzw. Unittest finden lässt. Allerdings haben wir hier auch andere Anforderungen an Verifikation und Testabdeckung als in einem Hobby-Projekt.
Gruß Kimmi
- Top-OR
- Establishment
- Beiträge: 330
- Registriert: 02.03.2011, 16:32
- Echter Name: Jens H.
- Wohnort: Esslingen/Dessau
- Kontaktdaten:
Re: Unit Testing unter C++ (Win32, MSVC)
Hallo Allerseits,
zuerst noch ein gutes neues Jahr 2015.
Ich sehe das mit den Unit-Tests ähnlich, wie ich bei vielen hier mehr oder weniger direkt rauslesen.
Es gibt bestimmte Dinge, für die Unit-Tests wichtig sind .. auch eher indirekte Dinge wie "besser überlegen, wie dinge gekapselt" werden.
Trotzdem sehe ichs nicht als Allheilmittel - was sie ja auch explizit nicht sein möchten - aber von einigen in meinem Kollegenkreise zur Zeit, zumindest emotional, so "gepusht" werden.
Naja, ich denke, das wird sich auf ein vernünftiges Maß einregeln.
Wem noch etwas dazu einfällt - also Unit-Tests für C++ unter Windows - besonders wenns vielleicht ne tolle parixnahe Seite oder ein Tutorial oder ne gute Library ist, der sei angehalten, sich hier kundzutun.
Ich werde das Thema ersmal sacken lassen und vielleicht später mal für mich umsetzen. Die Code-Basis, die abzudecken wäre, ist bisher auch nicht gerade klein ....
zuerst noch ein gutes neues Jahr 2015.
Ich sehe das mit den Unit-Tests ähnlich, wie ich bei vielen hier mehr oder weniger direkt rauslesen.
Es gibt bestimmte Dinge, für die Unit-Tests wichtig sind .. auch eher indirekte Dinge wie "besser überlegen, wie dinge gekapselt" werden.
Trotzdem sehe ichs nicht als Allheilmittel - was sie ja auch explizit nicht sein möchten - aber von einigen in meinem Kollegenkreise zur Zeit, zumindest emotional, so "gepusht" werden.
Naja, ich denke, das wird sich auf ein vernünftiges Maß einregeln.
Wem noch etwas dazu einfällt - also Unit-Tests für C++ unter Windows - besonders wenns vielleicht ne tolle parixnahe Seite oder ein Tutorial oder ne gute Library ist, der sei angehalten, sich hier kundzutun.
Ich werde das Thema ersmal sacken lassen und vielleicht später mal für mich umsetzen. Die Code-Basis, die abzudecken wäre, ist bisher auch nicht gerade klein ....
--
Verallgemeinerungen sind IMMER falsch.
Verallgemeinerungen sind IMMER falsch.
- kimmi
- Moderator
- Beiträge: 1405
- Registriert: 26.02.2009, 09:42
- Echter Name: Kim Kulling
- Wohnort: Luebeck
- Kontaktdaten:
Re: Unit Testing unter C++ (Win32, MSVC)
Schau mal hier: http://www.codeproject.com/Articles/696 ... ng-with-th
Dazu gibt es zu dem Thema ein recht gutes Buch: http://www.amazon.de/Modern-Programming ... evelopment
Und es macht wenig Sinn, alles nachträglich unit-zu-testen. Aber versuch doch mal, einen neuen Bug per Unittest reproduzierbar zu machen und fixe ihn. Wenn du das für jeden neuen durchhälst, kommst du nach und nach in den Genuss von automatisierten Tests.
Gruß Kimmi
Dazu gibt es zu dem Thema ein recht gutes Buch: http://www.amazon.de/Modern-Programming ... evelopment
Und es macht wenig Sinn, alles nachträglich unit-zu-testen. Aber versuch doch mal, einen neuen Bug per Unittest reproduzierbar zu machen und fixe ihn. Wenn du das für jeden neuen durchhälst, kommst du nach und nach in den Genuss von automatisierten Tests.
Gruß Kimmi
Re: Unit Testing unter C++ (Win32, MSVC)
Ich glaube Unit-Tests können toll sein wenn man auf der grünen Wiese beginnt. Wobei ich persönlich TDD nicht mag.
Wenn Du an einer über 20 Jahre gewachsenen Software mit mehr als 10000 unterschiedlichen Objekten arbeitest, dann kannst Du Unit Test's total vergessen weil der Code (Ausnahmen bestätigen die Regel) einfach völlig verwurschtelt ist und irgendwie alles mit allem zusammen hängt...
Sicher könnte man beginnen Dinge zu refactorn etc., jedoch stellt sich dann immer die Frage macht das Sinn (zeitlich) oder nicht.
Für das Produkt dessen Code ich im aktuell pflege, lautet die Antwort ganz klar "NEIN".
Am Ende sind Unit-Test's genau ein Werkzeug was ein bestimmtes Problem besser (im Sinne von einfacher/zeitsparender) löst als es manuell zu machen.
Ansonsten weiss ich das ich boost glaube ich Helferlein enthalten sind um Unit-Test's unter c++ zu verwenden. Praxiserfahrungen damit habe ich allerdings nicht.
Wenn Du an einer über 20 Jahre gewachsenen Software mit mehr als 10000 unterschiedlichen Objekten arbeitest, dann kannst Du Unit Test's total vergessen weil der Code (Ausnahmen bestätigen die Regel) einfach völlig verwurschtelt ist und irgendwie alles mit allem zusammen hängt...
Sicher könnte man beginnen Dinge zu refactorn etc., jedoch stellt sich dann immer die Frage macht das Sinn (zeitlich) oder nicht.
Für das Produkt dessen Code ich im aktuell pflege, lautet die Antwort ganz klar "NEIN".
Am Ende sind Unit-Test's genau ein Werkzeug was ein bestimmtes Problem besser (im Sinne von einfacher/zeitsparender) löst als es manuell zu machen.
Ansonsten weiss ich das ich boost glaube ich Helferlein enthalten sind um Unit-Test's unter c++ zu verwenden. Praxiserfahrungen damit habe ich allerdings nicht.