Ich arbeite an einer C ++ - Bibliothek, die (neben anderen Dingen) Funktionen zum Lesen von Konfigurationsdateien hat; und ich möchte Tests dafür hinzufügen. Bis jetzt hat mich dies dazu gebracht, viele gültige und ungültige Konfigurationsdateien zu erstellen, jede mit nur wenigen Zeilen, die eine bestimmte Funktionalität testen. Aber es ist jetzt sehr unhandlich geworden, da es so viele Dateien und auch viele kleine C ++ Test Apps gibt. Irgendwie erscheint mir das falsch :-) Also haben Sie Hinweise, wie Sie all diese Tests, die Test-Apps und die Testdaten organisieren?
Hinweis: Die öffentliche API der Bibliothek selbst ist nicht leicht zu testen (erfordert eine Konfigurationsdatei als Parameter). Die saftigen, fehleranfälligen Methoden zum tatsächlichen Lesen und Interpretieren von Konfigurationswerten sind privat, daher sehe ich keine Möglichkeit, sie direkt zu testen?
Also: würdest du beim Testen gegen echte Dateien bleiben? und wenn ja, wie würden Sie all diese Dateien und Anwendungen so organisieren, dass sie noch wartbar sind?
Vielleicht könnte die Bibliothek irgendeine Stream-Eingabe akzeptieren, so dass Sie ein string-ähnliches Objekt übergeben und alle Eingabedateien vermeiden könnten? Je nach Art der Konfiguration können Sie die Funktionen "get / setAttribute ()" verwenden, um die Parameter direkt zu publizieren und zu manipulieren. Wenn das nicht wirklich ein Designziel ist, dann macht es nichts. Datengetriebene Komponententests sind an einigen Stellen verpönt, aber definitiv besser als nichts! Ich würde wahrscheinlich den Code so auslegen:
%Vor%In jedem testN-Verzeichnis haben Sie eine cpp-Datei, die den Konfigurationsdateien im Eingabeverzeichnis zugeordnet ist.
Dann vorausgesetzt, Sie eine xUnit-Stil Testbibliothek verwenden ( cppunit , googletest , Unittest ++ , oder was auch immer) können Sie verschiedene testXXX hinzufügen ( ) Funktionen zu einer einzelnen Klasse, um damit verbundene Funktionsgruppen zu testen. Auf diese Weise könnten Sie einen Teil des Problems der vielen kleinen Programme aussparen, indem Sie zumindest einige Tests zusammenfassen.
Das einzige Problem dabei ist, wenn die Bibliothek erwartet, dass die Konfigurationsdatei als etwas Spezifisches oder an einem bestimmten Ort aufgerufen wird. Das sollte nicht der Fall sein, aber falls dies der Fall sein sollte, müssten Sie Ihre Testdatei an den erwarteten Speicherort kopieren.
Und mach dir keine Sorgen über viele Tests, die dein Projekt überladen, wenn sie in einem Testverzeichnis versteckt sind, dann werden sie niemanden stören.
Teil 1.
Wie Richard vorgeschlagen hat, würde ich mir den CPPUnit -Testframework ansehen. Das wird den Standort Ihres Test-Frameworks bis zu einem gewissen Grad bestimmen.
Ihre Tests könnten sich in einem parallelen Verzeichnis befinden, das sich auf einer höheren Ebene befindet, wie in Richards Beispiel, oder in Testunterverzeichnissen oder Testverzeichnissen, die parallel zu dem Bereich sind, den Sie testen möchten.
Wie auch immer, bitte seien Sie konsistent in der Verzeichnisstruktur des Projekts! Vor allem , wenn Tests in einem einzelnen übergeordneten Verzeichnis enthalten sind.
Es gibt nichts Schlimmeres als eine mentale Zuordnung des Quellcodes an einem Ort wie:
%Vor%und den / die Test (s) irgendwo finden wie:
%Vor%Und ich habe an Projekten gearbeitet, wo jemand das gemacht hat!
Was für eine Verschwendung von Wetware Zyklen! 8-O Sprechen Sie darüber, dass Sie Alexanders Konzept der Qualität ohne Namen verletzt haben.
Viel besser ist es, wenn Sie Ihre Tests konsistent finden, w.r.t. Ort des zu testenden Quellcodes:
%Vor%Teil 2
Nehmen Sie für die API-Konfigurationsdateien lokale Kopien einer Referenzkonfiguration in jedem lokalen Testbereich als Teil des Test-Env vor. Setup, das vor dem Ausführen eines Tests ausgeführt wird. Bestreuen Sie keine Kopien von Konfigurationsdaten (oder Daten) in Ihrer Teststruktur.
HTH.
Prost,
Rob
Übrigens, ich bin wirklich froh zu sehen, dass Sie das jetzt fragen, wenn Sie Dinge aufstellen!
Bei einigen Tests habe ich den Testcode verwendet, um die Konfigurationsdateien zu schreiben und sie dann zu löschen, nachdem der Test die Datei verwendet hat. Es pusht den Code etwas aus und ich habe keine Ahnung, ob es eine gute Übung ist, aber es hat funktioniert. Wenn Sie Boost verwenden, ist das Dateisystemmodul nützlich zum Erstellen von Verzeichnissen, zum Navigieren in Verzeichnissen und zum Entfernen der Dateien.
Für solche Dinge habe ich immer eine kleine Utility-Klasse, die eine Konfiguration in einen Speicherpuffer lädt und von dort in die eigentliche config-Klasse einspeist. Das bedeutet, dass die echte Quelle keine Rolle spielt - es könnte eine Datei oder eine db sein. Für den Komponententest ist es fest in einer std :: string codiert, die dann an die Klasse zum Testen übergeben wird. Sie können currup! Pte3d-Daten zum Testen von Fehlerpfaden einfach simulieren.
Ich verwende UnitTest ++ . Ich habe die Tests als Teil des Src-Baumes. Also:
%Vor%Angenommen, Sie haben die Kontrolle über das Design der Bibliothek, würde ich erwarten, dass Sie so umgestalten könnten, dass Sie die Bedenken beim tatsächlichen Lesen von Dateien von der Interpretation als Konfigurationsdatei trennen:
Um nun FileReader zu testen, benötigen Sie eine sehr kleine Anzahl von tatsächlichen Dateien (leer, binär, Klartext usw.), und für ConfigFileInterpreter würden Sie einen Stub der FileReader-Klasse verwenden, die einen Eingabestream zurückliefert. Jetzt können Sie alle Ihre verschiedenen Konfigurations-Situationen als Zeichenfolgen vorbereiten und Sie müssen nicht so viele Dateien lesen.
Sie werden kein Unit-Testing-Framework finden, das schlechter ist als CppUnit. Ernsthaft, jeder, der CppUnit empfiehlt, hat sich keines der konkurrierenden Frameworks angesehen.
Also ja, gehen Sie für eine Unit, die franework testet, aber benutzen Sie nicht CppUnit.
Tags und Links unit-testing c++ testing