Ich habe so etwas:
public byte[] EncodeMyObject(MyObject obj)
Ich habe Unit-Tests wie folgt durchgeführt:
byte[] expectedResults = new byte[3]{ 0x01, 0x02, 0xFF };
Assert.IsEqual(expectedResults, EncodeMyObject(myObject));
EDIT: Die zwei Möglichkeiten, die ich vorgeschlagen habe, sind:
1) Verwenden Sie fest codierte Erwartungswerte wie im obigen Beispiel.
2) Verwenden eines Decoders zum Decodieren des codierten Bytearrays und Vergleichen der Eingabe- / Ausgabeobjekte.
Das Problem, das ich bei Methode 1 sehe, ist, dass es sehr spröde ist und viele hartcodierte Werte erfordert.
Das Problem bei Methode 2 besteht darin, dass das Testen des Encoders davon abhängt, ob der Decoder ordnungsgemäß funktioniert. Wenn der Codierer / Decodierer gleichmäßig (an derselben Stelle) defekt ist, können die Tests zu falsch positiven Ergebnissen führen.
Dies sind möglicherweise die einzigen Möglichkeiten, um diese Art von Methode zu testen. Wenn das der Fall ist, dann gut. Ich stelle die Frage, ob es bessere Strategien für diese Art von Tests gibt. Ich kann die Interna des jeweiligen Encoders, an dem ich arbeite, nicht preisgeben. Ich frage im Allgemeinen, wie Sie diese Art von Problem lösen würden, und ich halte die Interna nicht für wichtig. Angenommen, ein bestimmtes Eingabeobjekt erzeugt immer dasselbe Ausgabebyte-Array.
quelle
myObject
weitermyObject
nach{ 0x01, 0x02, 0xFF }
? Kann dieser Algorithmus aufgeschlüsselt und getestet werden? Der Grund, den ich frage, ist derzeit, es sieht so aus, als hätten Sie einen Test, der beweist, dass eine magische Sache eine andere magische Sache hervorbringt. Ihr einziges Vertrauen ist, dass der eine Eingang den einen Ausgang erzeugt. Wenn Sie den Algorithmus aufschlüsseln können, können Sie weiteres Vertrauen in den Algorithmus gewinnen und weniger auf magische Ein- und Ausgänge angewiesen sein.Antworten:
Sie befinden sich dort in einer unangenehmen Situation. Wenn Sie ein statisches Format hätten, in das Sie codieren, wäre Ihre erste Methode der richtige Weg. Wenn es nur Ihr eigenes Format wäre und niemand anders dekodieren müsste, wäre die zweite Methode der richtige Weg. Aber Sie passen nicht wirklich in eine dieser Kategorien.
Ich würde versuchen, die Dinge nach Abstraktionsebenen aufzuschlüsseln.
Also würde ich mit etwas auf der Bitebene beginnen, das ich so etwas testen würde
Die Idee ist also, dass der Bitwriter weiß, wie man die primitivsten Arten von Feldern wie Ints schreibt.
Komplexere Typen würden implementiert und getestet wie:
Beachten Sie, dass dadurch vermieden wird, dass Sie wissen, wie die tatsächlichen Bits gepackt werden. Das wurde vom vorherigen Test getestet, und für diesen Test gehen wir so ziemlich einfach davon aus, dass es funktioniert.
Dann hätten wir auf der nächsten Abstraktionsebene
Daher versuchen wir auch hier nicht, das Wissen darüber einzubeziehen, wie Varstrings, Datumsangaben oder Zahlen tatsächlich codiert sind. In diesem Test interessiert uns nur die von encodeObject erzeugte Codierung.
Das Endergebnis ist, dass Sie, wenn das Format für Datumsangaben geändert wird, die Tests korrigieren müssen, die tatsächlich Datumsangaben enthalten. Alle anderen Codes und Tests befassen sich jedoch nicht damit, wie Datumsangaben tatsächlich codiert werden und sobald Sie den zu erstellenden Code aktualisieren diese Arbeit, alle diese Tests werden gut bestehen.
quelle
Hängt davon ab. Wenn die Codierung vollständig festgelegt ist und jede Implementierung genau dieselbe Ausgabe erstellen soll, ist es nicht sinnvoll, etwas anderes zu überprüfen, als zu überprüfen, ob die Beispieleingaben genau den erwarteten Ausgaben zugeordnet sind. Das ist der offensichtlichste Test und wahrscheinlich auch der am einfachsten zu schreibende.
Wenn bei alternativen Ausgaben wie im MPEG-Standard Spielraum vorhanden ist (z. B. gibt es bestimmte Operatoren, die Sie auf die Eingabe anwenden können, aber Sie können den Codierungsaufwand gegen die Ausgabequalität oder den Speicherplatz abwägen), ist es besser, die zu verwenden Definieren Sie die Dekodierungsstrategie für die Ausgabe und stellen Sie sicher, dass sie mit der Eingabe identisch ist. Wenn die Codierung verlustbehaftet ist, liegt sie relativ nahe an der ursprünglichen Eingabe. Das ist schwieriger zu programmieren, schützt Sie jedoch vor zukünftigen Verbesserungen an Ihrem Encoder.
quelle
Testen Sie das
encode(decode(coded_value)) == coded_value
unddecode(encode(value)) == value
. Sie können den Tests eine zufällige Eingabe geben, wenn Sie möchten.Es ist immer noch möglich, dass sowohl der Encoder als auch der Decoder auf komplementäre Weise defekt sind, aber das scheint ziemlich unwahrscheinlich, es sei denn, Sie haben ein konzeptionelles Missverständnis des Codierungsstandards. Das Durchführen von hartcodierten Tests des Codierers und Decodierers (wie Sie es bereits tun) sollte sich davor schützen.
Wenn Sie Zugriff auf eine andere Implementierung haben, von der bekannt ist, dass sie funktioniert, können Sie sie zumindest verwenden, um sicher zu sein, dass Ihre Implementierung gut ist, auch wenn die Verwendung in den Komponententests unmöglich wäre.
quelle
decode(encode(char))
wäre dies nicht gleichchar
(es wäre gleichchar+2
).Testen Sie die Anforderungen .
Wenn die Anforderungen nur "In einen Byte-Stream codieren, der beim Decodieren ein äquivalentes Objekt erzeugt" sind, testen Sie den Encoder einfach durch Decodieren. Wenn Sie sowohl den Encoder als auch den Decoder schreiben, testen Sie sie einfach zusammen. Sie können keine "Übereinstimmungsfehler" haben. Wenn sie zusammenarbeiten, besteht der Test.
Wenn es andere Anforderungen für den Datenstrom gibt, müssen Sie diese testen, indem Sie die codierten Daten untersuchen.
Wenn das codierte Format vordefiniert ist, müssen Sie entweder die codierten Daten wie erwartet anhand des erwarteten Ergebnisses überprüfen oder (besser) einen Referenzdecoder erhalten, dem Sie bei der Überprüfung vertrauen können. Durch die Verwendung eines Referenzdecoders wird die Möglichkeit ausgeschlossen, dass Sie die Formatspezifikation falsch interpretiert haben.
quelle
Abhängig von dem von Ihnen verwendeten Testframework und -paradigma können Sie weiterhin das Arrange Act Assert-Muster verwenden, wie Sie bereits gesagt haben.
Sie sollten die Anforderungen für
EncodeMyObject()
dieses Muster kennen und es verwenden können, um anhand jedes dieser Kriterien gültige und ungültige Kriterien zu testen, indem Sie jedes von ihnen anordnen und das erwartete Ergebnis fürexpected
, ähnlich für den Decoder, fest codieren .Da die erwarteten fest codiert sind, sind diese zerbrechlich, wenn Sie eine massive Änderung haben.
Möglicherweise können Sie mit etwas Parametergesteuertem automatisieren (siehe Pex ) oder, wenn Sie DDD oder BDD ausführen, Gerkin / Gurke .
quelle
Sie können entscheiden, was Ihnen wichtig ist.
Ist es Ihnen wichtig, dass ein Objekt die Rundreise überlebt und das genaue Drahtformat nicht wirklich wichtig ist? Oder ist das genaue Drahtformat ein wichtiger Bestandteil der Funktionalität Ihres Encoders und Decoders?
Wenn erstere, dann stellen Sie einfach sicher, dass Objekte die Rundreise überleben. Wenn sowohl der Encoder als auch der Decoder genau komplementär defekt sind, ist es Ihnen eigentlich egal.
In letzterem Fall müssen Sie testen, ob das Drahtformat für die angegebenen Eingänge den Erwartungen entspricht. Dies bedeutet, entweder das Format direkt zu testen oder eine Referenzimplementierung zu verwenden. Wenn Sie jedoch die Grundlagen getestet haben, können Sie zusätzliche Round-Trip-Tests nutzen, die sich leichter in Volumen schreiben lassen.
quelle