- Diese Frage bezieht sich nicht auf Unit Testing Frameworks.
- Bei dieser Frage geht es nicht darum, Komponententests zu schreiben.
- Bei dieser Frage geht es darum, wo der UT-Code geschrieben werden soll und wie / wann / wo er kompiliert und ausgeführt werden soll.
Das behauptet Michael Feathers, wenn er effektiv mit Legacy-Code arbeitet
gute Unit-Tests ... schnell laufen
und das
Ein Unit-Test, dessen Ausführung 1/10 Sekunde dauert, ist ein langsamer Unit-Test.
Ich halte diese Definitionen für sinnvoll. Ich denke auch, dass sie implizieren, dass Sie eine Reihe von Unit-Tests und eine Reihe von Code-Tests, die länger dauern, separat aufbewahren müssen, aber ich denke, das ist der Preis, den Sie bezahlen, wenn etwas nur einen Unit-Test nennt, wenn es (sehr) schnell läuft .
Offensichtlich besteht das Problem in C ++ darin, dass Sie zum "Ausführen" Ihrer Unit-Tests Folgendes tun müssen:
- Bearbeiten Sie Ihren Code (Produktion oder Komponententest, je nachdem, in welchem "Zyklus" Sie sich befinden)
- Kompilieren
- Verknüpfung
- Start Unit Test Executable ( s )
Bearbeiten (nach seltsamer enger Abstimmung) : Bevor ich auf die Details eingehe, werde ich versuchen, den Punkt hier zusammenzufassen:
Wie kann C ++ Unit Test-Code effektiv organisiert werden, so dass es effizient ist, den (Test-) Code zu bearbeiten und den Testcode auszuführen?
Das erste Problem ist dann, zu entscheiden, wo der Unit-Test-Code abgelegt werden soll, damit:
- Es ist "natürlich", sie in Kombination mit dem zugehörigen Produktionscode zu bearbeiten und anzuzeigen.
- Es ist einfach / schnell, den Kompilierungszyklus für die Einheit zu starten, die Sie gerade ändern
Das zweite verwandte Problem ist dann, was zu kompilieren ist , damit die Rückmeldung sofort erfolgt.
Extreme Möglichkeiten:
- Jede Unit-Test-Test-Unit befindet sich in einer separaten cpp-Datei und diese cpp-Datei wird separat kompiliert und (zusammen mit der Quellcode-Unit-Datei, die sie testet) mit einer einzelnen ausführbaren Datei verknüpft, die dann diesen einen Unit-Test ausführt.
- (+) Dies minimiert die Startzeit (Kompilieren + Verknüpfen!) Für die einzelne Testeinheit.
- (+) Der Test läuft super schnell, da nur eine Einheit getestet wird.
- (-) Um die gesamte Suite auszuführen, müssen eine Unmenge von Prozessen gestartet werden. Kann ein Problem sein, zu handhaben.
- (-) Der Overhead von Prozessstarts wird sichtbar
- Die andere Seite wäre - noch - eine cpp-Datei pro Test, aber alle Test-cpp-Dateien (zusammen mit dem Code, den sie testen!) Sind zu einer ausführbaren Datei verknüpft (pro Modul / pro Projekt / nach Wahl).
- (+) Die Kompilierungszeit wäre noch in Ordnung, da nur geänderter Code kompiliert wird.
- (+) Das Ausführen der gesamten Suite ist einfach, da nur eine Exe ausgeführt werden muss.
- (-) Das Verknüpfen der Suite wird einige Zeit in Anspruch nehmen, da jedes erneute Kompilieren eines Objekts ein erneutes Verknüpfen auslöst.
- (-) (?) Der Anzug braucht länger, obwohl die Zeit in Ordnung sein sollte , wenn alle Unit-Tests schnell sind.
Wie werden C ++ - Komponententests in der Praxis gehandhabt? Wenn ich das Zeug nur jede Nacht / Stunde laufen lasse, spielt der zweite Teil keine Rolle, aber der erste Teil, nämlich wie man den UT-Code mit dem Produktionscode "koppelt", so dass es für Entwickler "natürlich" ist, beides beizubehalten Fokus ist immer wichtig, denke ich. (Und wenn Entwickler den UT-Code im Fokus haben, werden sie ihn ausführen wollen, was uns zu Teil zwei zurückführt.)
Geschichten und Erfahrungen aus der realen Welt werden geschätzt!
Anmerkungen:
- Diese Frage lässt absichtlich eine nicht spezifizierte Plattform und ein nicht spezifiziertes Hersteller- / Projektsystem übrig.
- Fragen mit dem Tag UT & C ++ ist ein guter Anfang, aber leider konzentrieren sich zu viele Fragen und insbesondere Antworten zu stark auf die Details oder auf bestimmte Frameworks.
- Vor einiger Zeit beantwortete ich eine ähnliche Frage zur Struktur für Boost-Unit-Tests. Ich finde, dass diese Struktur für "echte", schnelle Unit-Tests fehlt. Und ich finde die andere Frage zu eng, daher diese neue Frage.
:-(
Wo soll man nach Antworten auf solche Fragen suchen, wenn nicht in diesem Forum?
Pipeline<A,B>.connect(Pipeline<B,C>)
die kompiliert werden sollte, während Pipeline<A,B>.connect(Pipeline<C,D>)
sie nicht kompiliert werden sollte: Der Ausgabetyp der ersten Stufe ist nicht kompatibel mit dem Eingabetyp der zweiten Stufe.