Wenn Sie eine Aufzählung nur mit Werten haben (keine Methoden wie in Java) und diese Aufzählung Teil der Geschäftsdefinition des Systems ist, sollte man Unit-Tests dafür schreiben?
Ich dachte, dass sie geschrieben werden sollten, auch wenn sie einfach und überflüssig erscheinen könnten. Ich denke, dass was die Geschäftsspezifikation betrifft, explizit in einem Test geschrieben werden sollte, sei es mit unit / integration / ui / etc. Tests oder unter Verwendung des Typsystems der Sprache als Testmethode. Da die Werte, die eine Aufzählung (z. B. in Java) aus Sicht des Geschäfts haben muss, nicht mit dem Typsystem getestet werden können, sollte es meiner Meinung nach einen Komponententest dafür geben.
Diese Frage ist nicht ähnlich diesen , da es nicht das gleiche Problem wie ich nicht ansprechen. In dieser Frage gibt es eine Business Function (savePeople) und die Person fragt nach der internen Implementierung (forEach). Darin befindet sich eine mittlere Business-Schicht (die Funktion save people), die das Sprachkonstrukt (forEach) kapselt. Hier ist das Sprachkonstrukt (enum) dasjenige, das verwendet wird, um das Verhalten von einem geschäftlichen Standpunkt aus zu spezifizieren.
In diesem Fall stimmt das Implementierungsdetail mit der "wahren Natur" der Daten überein, d. H. Einer Menge (im mathematischen Sinne) von Werten. Sie könnten wohl eine unveränderliche Menge verwenden, aber die gleichen Werte sollten dort immer noch vorhanden sein. Wenn Sie ein Array verwenden, müssen Sie das Gleiche tun, um die Geschäftslogik zu testen. Ich denke, das Rätsel hier ist die Tatsache, dass das Sprachkonstrukt sehr gut mit der Art der Daten übereinstimmt. Ich bin mir nicht sicher, ob ich mich richtig erklärt habe
quelle
Antworten:
Nein, sie sind nur staatlich.
Grundsätzlich ist die Tatsache, dass Sie eine Aufzählung verwenden, ein Implementierungsdetail . Das ist die Art von Dingen, die Sie in der Lage sein möchten, in ein anderes Design umzugestalten.
Das Testen von Aufzählungen auf Vollständigkeit ist analog zum Testen, ob alle darstellbaren ganzen Zahlen vorhanden sind.
Das Testen des von den Enumerationen unterstützten Verhaltens ist jedoch eine gute Idee. Mit anderen Worten, wenn Sie von einer bestandenen Testsuite ausgehen und einen einzelnen Enum-Wert auskommentieren, sollte mindestens ein Test fehlschlagen (Kompilierungsfehler gelten als Fehler).
quelle
Hearts
,Spades
,Diamonds
,Clubs
] wenn du nur jemals eine karte wenn eine karte rot / schwarz ist?null_ptr
Fehler auslösen . Das hat jetzt einen Fehlercode über die Enumeration. Die Code-Überprüfung auf einennull_ptr
Fehler schlägt den Code auch über die Aufzählung nach. So kann es einen Wert von5
(zum Beispiel) haben. Jetzt müssen Sie einen weiteren Fehlercode hinzufügen. Die Aufzählung wurde geändert (sagen wir, wir fügen oben in der Aufzählung eine neue hinzu). Der Wert vonnull_ptr
ist jetzt6
. Ist das ein Problem? Sie geben jetzt einen Fehlercode von zurück6
und testen auf6
. Solange alles logisch konsistent ist, geht es Ihnen gut, obwohl diese Änderung Ihren theoretischen Test durchbrochen hat.Sie testen keine Enum- Deklaration . Sie können testen, ob der Funktionseingang / -ausgang die erwarteten Aufzählungswerte aufweist. Beispiel:
Sie schreiben keine Tests, in denen überprüft wird, ob enum
Parity
die NamenEven
und definiertOdd
. Ein solcher Test wäre sinnlos, da Sie nur wiederholen würden, was bereits im Code angegeben ist. Wenn Sie dasselbe zweimal sagen, wird es nicht korrekter.Sie tun Schreibtests Überprüfung
GetParity
Mitsprache zurückEven
für 0,Odd
1 und so weiter. Dies ist hilfreich, da Sie den Code nicht wiederholen, sondern das Verhalten des Codes unabhängig von der Implementierung überprüfen. Wenn der CodeGetParity
komplett neu geschrieben würde, wären die Tests immer noch gültig. Der Hauptvorteil von Komponententests besteht darin, dass Sie Code sicher umschreiben und umgestalten können, indem Sie sicherstellen, dass der Code weiterhin wie erwartet funktioniert.Wenn Sie jedoch einen Test haben, der sicherstellt, dass eine Enum- Deklaration die erwarteten Namen definiert, müssen Sie den Test auch ändern, wenn Sie in Zukunft Änderungen an der Enum-Liste vornehmen. Dies bedeutet, dass es nicht nur doppelt so viel Arbeit ist, sondern auch, dass der Nutzen für den Komponententest verloren geht. Wenn Sie Code und Test am ändern müssen gleichzeitig , dann gibt es keinen Schutz gegen die Einführung Bugs.
quelle
Wenn das Risiko besteht, dass das Ändern der Aufzählung Ihren Code beschädigt, ist alles mit dem Attribut [Flags] in C # ein guter Fall, da das Hinzufügen eines Werts zwischen 2 und 4 (3) eine bitweise 1 und 2 anstelle von a wäre diskreter Artikel.
Es ist eine Schutzschicht.
Sie sollten in Betracht ziehen, einen Enum-Verhaltenskodex zu haben, mit dem alle Entwickler vertraut sind. Verlassen Sie sich nicht auf Textdarstellungen der Aufzählung, da diese häufig vorkommen. Dies kann jedoch zu Konflikten mit Ihren Serialisierungsrichtlinien führen.
Ich habe gesehen, wie Leute die Großschreibung von Aufzählungs-Einträgen "korrigiert" haben, sie alphabetisch oder nach einer anderen logischen Gruppierung sortiert haben, die alle andere fehlerhafte Code-Teile gebrochen hat.
quelle
Nein, ein Test, bei dem überprüft wird, ob eine Aufzählung alle gültigen Werte enthält und nicht mehr, wiederholt im Wesentlichen die Deklaration der Aufzählung. Sie würden nur testen, ob die Sprache das Enum-Konstrukt ordnungsgemäß implementiert, was ein sinnloser Test ist.
Davon abgesehen sollten Sie das Verhalten testen, das von den Aufzählungswerten abhängt. Wenn Sie zum Beispiel die Aufzählungswerte verwenden, um Entitäten nach json oder was auch immer zu serialisieren, oder die Werte in einer Datenbank speichern, sollten Sie das Verhalten für alle Werte der Aufzählung testen. Auf diese Weise sollte, wenn die Aufzählung geändert wird, mindestens einer der Tests fehlschlagen. Was Sie auf jeden Fall testen würden, ist das Verhalten um Ihre Aufzählung, nicht die Aufzählung Deklaration selbst.
quelle
Ihr Code sollte korrekt funktionieren, unabhängig von den tatsächlichen Werten einer Aufzählung. In diesem Fall sind keine Komponententests erforderlich.
Möglicherweise haben Sie jedoch Code, bei dem das Ändern eines Enum-Werts zu Problemen führt. Wenn beispielsweise ein Aufzählungswert in einer externen Datei gespeichert ist und nach dem Ändern des Aufzählungswerts das Lesen der externen Datei das falsche Ergebnis liefert. In diesem Fall wird in der Nähe der Aufzählung ein GROSSER Kommentar angezeigt, der jeden warnt, keine Werte zu ändern, und Sie können sehr gut einen Komponententest schreiben, der die numerischen Werte überprüft.
quelle
Im Allgemeinen ist es nicht besonders wertvoll, nur zu überprüfen, ob eine Aufzählung eine fest codierte Liste von Werten enthält, wie in anderen Antworten angegeben, da Sie dann nur Test und Aufzählung gemeinsam aktualisieren müssen.
Ich hatte einmal den Fall, dass ein Modul Aufzählungstypen von zwei anderen Modulen verwendete und zwischen ihnen abbildete. (Eine der Aufzählungen hatte zusätzliche Logik, die andere war für den DB-Zugriff, beide hatten Abhängigkeiten, die voneinander isoliert werden sollten.)
In diesem Fall habe ich einen Test (im Mapping-Modul) hinzugefügt, der überprüft hat, dass alle Enum-Einträge im Quell-Enum auch im Ziel-Enum vorhanden sind (und somit das Mapping immer funktionieren würde). (In einigen Fällen habe ich auch umgekehrt nachgesehen.)
Auf diese Weise schlug ein Test fehl, wenn jemand einen Listeneintrag zu einer der Listen hinzufügte und vergaß, den entsprechenden Eintrag zu der anderen hinzuzufügen.
quelle
Aufzählungen sind einfach endliche Typen mit benutzerdefinierten (hoffentlich aussagekräftigen) Namen. Eine Aufzählung kann nur einen Wert haben,
void
der nur enthältnull
(einige Sprachen nennen diesunit
und verwenden den Namenvoid
für eine Aufzählung ohne Elemente!). Es kann zwei Werte haben, wiebool
das hatfalse
undtrue
. Es kann drei, wiecolourChannel
mitred
,green
undblue
. Und so weiter.Wenn zwei Aufzählungen die gleiche Anzahl von Werten haben, sind sie "isomorph". dh wenn wir alle Namen systematisch austauschen, können wir einen anstelle des anderen verwenden und unser Programm wird sich nicht anders verhalten. Insbesondere verhalten sich unsere Tests nicht anders!
Zum Beispiel
result
enthältwin
/lose
/draw
ist isomorph zum obencolourChannel
, da wir ersetzen kann zBcolourChannel
mitresult
,red
mitwin
,green
mitlose
undblue
mitdraw
, und so lange , wie wir dies tun , überall (Erzeuger und Verbraucher, Parser und Serializer, Datenbankeinträge, Log - Dateien, usw. ) dann wird sich an unserem Programm nichts ändern. Alle "colourChannel
Tests", die wir geschrieben haben, werden immer noch bestehen, auch wenn es keine gibtcolourChannel
keine mehr gibt!Wenn eine Aufzählung mehr als einen Wert enthält, können wir diese Werte jederzeit neu anordnen , um eine neue Aufzählung mit der gleichen Anzahl von Werten zu erhalten. Da sich die Anzahl der Werte nicht geändert hat, ist die neue Anordnung gegenüber der alten isomorph, sodass wir alle Namen austauschen konnten und unsere Tests weiterhin bestanden würden (beachten Sie, dass dies nicht möglich ist die Definition einfach austauschen müssen) alle nutzungsseiten auch noch ausschalten).
Dies bedeutet, dass für die Maschine Aufzählungen "unterscheidbare Namen" und nichts anderes sind . Das einzige, was wir mit einer Enumeration machen können, ist zu verzweigen, ob zwei Werte gleich (zB
red
/red
) oder verschieden (zBred
/blue
) sind. Das ist also das einzige, was ein "Unit-Test" tun kann, zWie @ jesm00 sagt, ein solcher Test die prüft Sprache Implementierung anstatt das Programm. Diese Tests sind niemals eine gute Idee: Auch wenn Sie der Sprachimplementierung nicht vertrauen, sollten Sie sie von außen testen , da es nicht vertrauenswürdig ist, die Tests korrekt auszuführen!
Das ist also die Theorie; was ist mit der Praxis? Das Hauptproblem bei dieser Charakterisierung von Aufzählungen ist, dass Programme der „realen Welt“ selten in sich geschlossen sind: Wir verfügen über ältere Versionen, Remote- / Embedded-Bereitstellungen, historische Daten, Backups, Live-Datenbanken usw., sodass wir nie wirklich „ausschalten“ können. Alle Vorkommen eines Namens, ohne dass Verwendungen fehlen.
Solche Dinge liegen jedoch nicht in der „Verantwortung“ der Aufzählung selbst: Das Ändern einer Aufzählung kann die Kommunikation mit einem entfernten System unterbrechen, aber umgekehrt können wir ein solches Problem durch Ändern einer Aufzählung beheben !
In solchen Szenarien ist die Enum eine rot-Hering: was passiert , wenn ein System muss es sein , diese Art und Weise, und ein anderer muss es sein , dass Art und Weise? Es kann nicht beides sein, egal wie viele Tests wir schreiben! Der eigentliche Schuldige ist hier die Eingabe- / Ausgabeschnittstelle, die wohldefinierte Formate erzeugen / konsumieren sollte und nicht "welche Ganzzahl die Interpretationsauswahl auch immer". Die eigentliche Lösung besteht also darin , die E / A-Schnittstellen zu testen : mit Komponententests, um zu überprüfen, ob das erwartete Format analysiert / gedruckt wird, und mit Integrationstests, um zu überprüfen, ob das Format tatsächlich von der anderen Seite akzeptiert wird.
Wir mögen uns immer noch fragen, ob das Enum 'gründlich genug trainiert' wird, aber in diesem Fall ist das Enum wieder ein roter Hering. Was uns eigentlich Sorgen macht, ist die Testsuite selbst . Wir können hier auf verschiedene Arten Vertrauen gewinnen:
red
und wir nur mit testenred
, haben wir eine 100% ige Abdeckung. Eine Eigenschaftsprüfung generiert (versucht) Gegenbeispiele zu unseren Behauptungen, wie z. B. das Generieren der Wertegreen
undblue
, die wir vergessen haben, zu testen.quelle
Unit Tests sind für das Testen von Units.
https://en.wikipedia.org/wiki/Unit_testing
Ein automatisierter Test für eine deklarierte Enumeration würde eher die Integrität der Sprache und der Plattform, auf der sie ausgeführt wird, als die Logik in Code testen, der vom Entwickler erstellt wurde. Es würde keinen nützlichen Zweck erfüllen - Dokumentation eingeschlossen, da der Code, der die Aufzählung deklariert, ebenso als Dokumentation dient wie Code, der es testen würde.
quelle
Es wird erwartet, dass Sie das beobachtbare Verhalten Ihres Codes und die Auswirkungen von Methoden- / Funktionsaufrufen auf den beobachtbaren Status testen. Solange der Code das Richtige für Sie ist, müssen Sie nichts weiter testen.
Sie müssen nicht explizit behaupten, dass ein Aufzählungstyp die von Ihnen erwarteten Einträge enthält, genauso wie Sie nicht explizit behaupten, dass eine Klasse tatsächlich vorhanden ist oder die von Ihnen erwarteten Methoden und Attribute aufweist.
Tatsächlich wird durch das Testen des Verhaltens implizit bestätigt, dass die am Test beteiligten Klassen, Methoden und Werte vorhanden sind, sodass Sie es nicht explizit bestätigen müssen.
Beachten Sie, dass Sie keine aussagekräftigen Namen für Ihren Code benötigen, um das Richtige zu tun. Dies ist nur eine Annehmlichkeit für die Leser Ihres Codes. Sie könnten Ihren Code mit Aufzählungswerten wie
foo
,bar
... und Methoden wie arbeiten lassenfrobnicate()
.quelle