Die Erkennung der C ++ - Struktur wird vom Komponententest aus aktualisiert

8

Ich habe eine Familie von Datenstrukturen, die mit boost :: serialization von einer Ebene zu einer anderen übergeben werden sollten. Zum Beispiel

%Vor%

Ich möchte Unit Tests dazu schreiben, nur um sicherzugehen, dass ich einige Felder nicht übersehen habe (es gibt viele Strukturen und Felder).

Das Problem ist, wenn ich ein neues Feld in der Struktur hinzufüge (ich werde es auf jeden Fall tun) und vergessen, den Komponententest zu aktualisieren, wird dieses Feld nicht vom Komponententest abgedeckt.

Meine Frage ist: Wie erkennt man, dass diese Struktur (oder Klasse) geändert wurde? Meine Idee war, static_assert (sizeof (DataType1) == HARD_CODED_VALUE) zu verwenden, aber es leidet an unterschiedlichen Strukturgrößen in verschiedenen Compilern, Plattformen (x64, x86) und Konfigurationen (release, debug).

Irgendeine gute Idee, wie man damit umgeht?

    
capone 29.05.2013, 10:10
quelle

7 Antworten

3
  

Das Problem ist, wenn ich ein neues Feld in der Struktur hinzufüge (ich werde das auf jeden Fall tun) und vergessen, den Komponententest zu aktualisieren, wird dieses Feld nicht vom Komponententest abgedeckt.

     

Meine Frage ist: Wie erkennt man, dass diese Struktur (oder Klasse) geändert wurde?

     

Meine Idee war, static_assert (sizeof (DataType1) == HARD_CODED_VALUE) [...]

zu verwenden

Das ist keine tragbare Lösung (wie Sie selbst bemerkt haben).

  

Irgendeine gute Idee, wie man damit umgeht?

Ja: Können Sie mit der Aktualisierung des Tests beginnen?

Das heißt, nicht entscheiden, was in der Struktur gehen soll, dann fügen Sie es hinzu, dann aktualisieren Sie die Tests (wenn Sie nicht vergessen).

Aktualisieren Sie stattdessen die Tests, um nach den neuen serialisierten Daten zu suchen, stellen Sie dann sicher, dass die aktualisierten Tests fehlschlagen, und aktualisieren Sie erst dann den Code, damit die Tests bestanden werden.

Dieser Ansatz (Einheitstest zuerst schreiben / aktualisieren) wurde (teilweise) erstellt, um genau dieses Problem anzugehen.

Der Test-First-Ansatz hat noch weitere Vorteile:

  • es vermeidet geschickt YAGNI

  • minimiert die vorzeitige Optimierung

  • es entwickelt sich auf natürliche Weise zur Überwachung der Funktionsvollständigkeit Ihrer Anwendung / Implementierung.

utnapistim 29.05.2013 11:05
quelle
2

Fügen Sie der Klassendefinition einen Kommentar hinzu, um Sie daran zu erinnern, dass Sie beim Hinzufügen von Mitgliedern den Serializer optimieren müssen. Es gibt Grenzen, was ein Computer für Sie tun könnte - deshalb ist Code Review wichtig. Lassen Sie alle Patches von einem anderen Programmierer überprüfen, haben Sie eine Reihe strenger Testfälle und hoffen Sie auf das Beste.

Ich bin sicher, du könntest z.B. schreibe ein clang-plugin, das sicherstellt, dass eine bestimmte Methode auf jedes Mitglied einer Struktur verweist, aber brauchst du das wirklich und kannst du deine Zeit darauf verwenden?

Das heißt, Sie haben Bonuspunkte, um so viel Arbeit wie möglich an den Computer auszulagern. Sogar der static_assert Trick ist ein guter. Wenn Sie es mit einer Menge von #ifdef s für eine bestimmte ABI und Architektur schützen, wo Sie oft genug bauen, könnte es eine gute Arbeit leisten.

    
Jan Kundrát 29.05.2013 10:21
quelle
1

Wie wäre es mit etwas wie:

%Vor%

Auf diese Weise müssen Sie nur Felder an einem Ort hinzufügen.

    
Asaf 29.05.2013 11:10
quelle
0

In Ihren Komponententests könnten Sie eine static_sert-Prüfung mit der erwarteten Struc-Größe durchführen:

%Vor%

Sie müssen die Größe der Struktur (die Nummer in der Überprüfung) pro Plattform (oder nur für eine Plattform) festlegen.

    
BЈовић 29.05.2013 10:40
quelle
0

Sie können Ihren Strukturen einfach die statische Variable "version" hinzufügen und sie erhöhen, wenn sich die Struktur ändert.

%Vor%

Dann schreibe in deinen Tests einfach

%Vor%

Aber Sie können immer noch vergessen, die Version zu aktualisieren, wenn Struktur ändern, oder vergessen, einige der neuen Mitglieder hinzuzufügen, wenn der Test aktualisiert wird.

    
user1837009 29.05.2013 10:43
quelle
0

Ich hatte ein ähnliches Problem und ich fand meine Lösung mit boost :: fusion. Hier können Sie über alle Mitglieder Ihrer Struktur iterieren. Man muss also nicht mehr manuell vorgehen. Außerdem bekommst du das nette Feature der Kompilier-Introspektion. So ist es einfach, den Inhalt der gesamten Struktur, z. in eine Protokolldatei mit einem liitle Vorlagencode.

    
Felix Petriconi 29.05.2013 11:52
quelle
0

Eine Craay-Methode besteht darin, Mitglieder nicht direkt zu verwenden.

Erstellen Sie eine aggregierte Variant-Vorlage. Erstellen Sie eine Datenelementvorlage.

Die Datenelementvorlage verwendet eine Tag-Struktur.

Überschreiben Sie data_member<tag,T>::operator^( tag ) , um einen Verweis auf T zurückzugeben. Mqybe macht das gleiche für die freie operator^( data_member< tag, T >*, tag )

Jetzt können Sie das Mitglied über this^tag() erhalten, was wie ein Mitgliederzugriff aussieht. Wenn Sie eine globale Instanz von tag erstellen, können Sie sogar () entfernen.

Sie haben auch eine Reflektion der Kompilierungszeit für Ihre Datenmitglieder. Sie können also for_each_member schreiben und Ihren gesamten Serialisierungscode einmal schreiben und für jedes struct verwenden.

Zugriffskontrolle und andere Kategorien von data_member können in der aggregate Vorlage vorgenommen werden.

Tag-basierte Konstruktion von Daten kann mit einem komplexen und ausgefallenen aggregate -Konstruktor gemacht werden.

Alternativ können Sie darauf warten, dass in C ++, wahrscheinlich innerhalb des Jahrzehnts, echte Reflektion auftaucht.

Alternativ können Sie Ihren struct in einen tuple -Wrapper umwandeln und etwas wie den obigen Override-Trick verwenden, um this^tag für einen namenbasierten Zugriff zu verwenden.

Wenn wir struct foo mit int x, y und double d haben, mit denen wir das tun möchten, könnten wir Folgendes tun:

%Vor%

Ein (schwerwiegendes) Problem besteht darin, dass zwei Membervariablen in zwei verschiedenen struct s denselben "Namespace" und denselben Konflikt haben, wenn sie denselben Namen haben.

    
Yakk 29.05.2013 12:08
quelle

Tags und Links