2008-10-09 13 views
8

Ich arbeite an einer C++ - Bibliothek, die (neben anderen Sachen) 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 können?Wie organisiert man C++ Test Apps und zugehörige Dateien?

Hinweis: Die öffentliche API der Bibliothek selbst ist nicht leicht zu testen (erfordert eine Konfigurationsdatei als Parameter). Die saftigen, fehleranfälligen Methoden, um Konfigurationswerte tatsächlich zu lesen und zu interpretieren, sind privat. Daher sehe ich keine Möglichkeit, sie direkt zu testen.

Also: würden Sie mit dem Testen gegen echte Dateien bleiben; Und wenn ja, wie würden Sie all diese Dateien und Apps so organisieren, dass sie noch wartbar sind?

Antwort

5

Vielleicht könnte die Bibliothek eine Art 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 oder 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 wie folgt auslegen:

project/ 
      src/ 
      tests/ 
       test1/ 
         input/ 
       test2 
         input/ 

In jedem TESTn Verzeichnis würden Sie eine CPP-Datei auf die Konfigurationsdateien im Eingabeverzeichnis zugeordnet.

Dann vorausgesetzt, Sie verwenden eine xUnit-Stil Testbibliothek (cppunit, googletest, unittest++, oder was auch immer) Sie können verschiedene testXXX() Funktionen zu einer einzigen Klasse hinzufügen zugehörige Gruppen von Funktionalität zu testen. Auf diese Weise konnten Sie einen Teil des Problems der vielen kleinen Programme aussparen, indem Sie zumindest einige Tests zusammenfassen.

Das einzige Problem damit ist, wenn die Bibliothek erwartet, dass die Konfigurationsdatei als etwas Bestimmtes 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 überfluten, wenn sie in einem Testverzeichnis versteckt sind, dann werden sie niemanden stören.

0

In einigen Tests habe ich tatsächlich 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, um Verzeichnisse zu erstellen, Verzeichnisse zu navigieren und die Dateien zu entfernen.

0

Ich stimme dem zu, was @Richard Quirk gesagt hat, aber Sie möchten vielleicht auch Ihre Testsuite-Klasse zu einem Freund der Klasse machen, die Sie testen, und ihre privaten Funktionen testen.

1

Teil 1.

Als Richard vorgeschlagen, würde ich am CPPUnit Test-Framework einen Blick darauf werfen. Das wird den Standort Ihres Test-Frameworks in gewissem Maße bestimmen.

Ihre Tests können 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, seien Sie bitte konsistent in der Verzeichnisstruktur des Projekts! Insbesondere, wenn Tests in einem einzelnen übergeordneten Verzeichnis enthalten sind.

Es gibt nichts Schlimmeres als eine gedankliche Zuordnung des Quellcodes in einem Ort wie pflegen zu müssen:

/project/src/component_a/piece_2/this_bit 

und mit der Prüfung (en) befindet sich irgendwo wie:

/project/test/the_first_components/connection_tests/test_a 

Und Ich habe an Projekten gearbeitet, wo jemand das getan 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, Ihre Tests konsequent w.r.t. Lage des Quellcodes im Test:

/project/test/component_a/piece_2/this_bit/test_a 

Teil 2

Wie für die API-Konfigurationsdateien, stellt lokale Kopien einer Referenz config in jedem lokalen Testbereich als Teil des Test env. Setup, das vor dem Ausführen eines Tests ausgeführt wird. Bestreuen Sie keine Kopien von Konfigs (oder Daten) in Ihrem gesamten Testbaum.

HTH.

prost,

Rob

BTW wirklich froh, Sie zu fragen, dies jetzt zu sehen, wenn die Dinge Einstellung!

0

Für solche Dinge habe ich immer eine kleine Utility-Klasse, die eine Config 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:

solution/project1/src <-- source code 
solution/project1/src/tests <-- unit test code 
solution/project2/src <-- source code 
solution/project2/src/tests <-- unit test code 
0

Unter der Annahme, dass Sie die Kontrolle über die Gestaltung der Bibliothek haben, würde ich erwarten, dass Sie in der Lage sein würden so zu umgestalten, dass Sie die Sorgen der eigentlichen Datei getrennt Lese von ihm als Konfigurationsdatei zu interpretieren:

  1. Klasse Filereader liest die Datei und erzeugt einen Eingangsstrom,
  2. Klasse ConfigFileInterpreter validiert/interpretiert usw., den Inhalt des Eingangsstroms

Nun, um 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.

0

Sie werden kein Unit-Testing-Framework finden, das schlechter als CppUnit ist. Ernsthaft, jeder, der CppUnit empfiehlt, hat sich keines der konkurrierenden Frameworks angesehen.

Also ja, gehen Sie für eine Unit testen Franework, aber nicht CppUnit verwenden.

Verwandte Themen