Verstößt Codierung und Unit-Test gegen das DRY-Prinzip?

8

Das Trockenprinzip besagt:

"Jedes Wissen muss eine einzige, eindeutige und maßgebliche Darstellung innerhalb eines Systems haben."

Wenn Sie jedoch Tests für Code schreiben, beschreiben Sie das erwartete Verhalten für das System zweimal (einmal im Code und einmal im Test). Ich weiß, dass beide Beschreibungen aus einer anderen Perspektive stammen, aber einen großen Teil der zugrunde liegenden Idee teilen.

Irgendwelche Gedanken dazu?

Im Allgemeinen halte ich beide Unit-Tests und das DRY-Prinzip für gute Ideen und versuche, sie so weit wie möglich anzuwenden. Diese Frage ist eher philosophisch, aber ich habe mich gefragt, ob jemand auch daran gedacht hat.

refro
quelle
4
1. Code ist nicht das erwartete Verhalten, sondern das tatsächliche Verhalten. 2. Der Test gehört nicht zum System, daher steht DRY weiterhin.
Mouviciel

Antworten:

12

Sie arbeiten unter einer fehlerhaften Prämisse.

Der Code ist keine Beschreibung des erwarteten Verhaltens, sondern nur die Anforderungen und Testfälle. Und selbst dann definieren die Anforderungen und Tests zwei Seiten des Verhaltens. Die Anforderungen definieren die Merkmale und Funktionen des gesamten Softwaresystems, und der Test definiert, wie die erwarteten Ergebnisse aussehen sollen, und wird mit den Anforderungen abgeglichen. Der Code ist eine Interpretation dieser Anforderungen und der Architektur des Systems durch den Entwickler.

Thomas Owens
quelle
Ich denke in die gleiche Richtung, jedoch mit einem Unterschied: Die Komponententests basieren auch auf der Interpretation der Anforderungen und der Architektur durch den Entwickler, sodass auf dieser Ebene kein Missverständnis zwischen Komponententests und Code bestehen kann (zumindest bei TDD auf der grünen Wiese) - Legacy-Code ist ein anderes Problem. Es sind die Abnahmetests, die auf der Definition der Anforderungen des Kunden basieren / basieren sollten.
Péter Török
@ PéterTörök Bei Unit-Tests kommt es darauf an, wer die Tests schreibt. Das ist absolut richtig, wenn derselbe Entwickler die Tests und den Code schreibt. Wenn ein Entwickler die Tests schreibt und einer den Code schreibt, haben Sie zwei Entwicklerinterpretationen und können Probleme früher erkennen. In Bezug auf verschiedene Teststufen verwende ich den Begriff "Test" für Einheiten-, Integrations-, System- und Abnahmetests, die jeweils von einer geeigneten Person oder Gruppe für den jeweiligen Zweck geschrieben wurden. Wenn die falschen Leute einen Test schreiben (z. B. ein Entwickler, der einen Abnahmetest schreibt), ist der Test nicht so nützlich.
Thomas Owens
6

Nein, es verstößt nicht gegen das DRY-Prinzip, da Unit-Tests die Funktionalität nicht reproduzieren, sondern nur sicherstellen, dass die Funktionalität (Re: Responsibility) ordnungsgemäß funktioniert. Im Falle eines Komponententests bleibt die Methode, die Sie testen, erhalten authoritative representation. Ihr Testcode sieht möglicherweise dem Code sehr ähnlich, der die Methode in der Produktionsversion implementiert, hat jedoch seinen eigenen eindeutigen Zweck (den Test zu bestätigen).

Joel Etherton
quelle
3

So'ne Art. Wenn sie sich zu ähnlich sind, ist das eine schlechte Sache. Ihr Test sollte nicht so codiert sein wie der Code, den er testet. Sie sollten also (1) eine Erwartung und (2) eine Implementierung definieren.

Ich denke gerne, dass es der doppelten Buchführung ähnelt . Ein Buchhaltungssystem macht immer mindestens 2 Einträge (eine Lastschrift und eine Gutschrift). Dies ist eine Fehlerprüfungsmaßnahme. Am Ende des Tages müssen die Belastungen und Gutschriften ausgeglichen werden, sonst ist ein Fehler aufgetreten. Sie können kein Fehlererkennungssystem ohne irgendeine Form von Redundanz haben.

Betrachten Sie zum Beispiel einen CRC . Ihr CRC-Byte ist eine Form der Redundanz. Es reicht aus, um einen kleinen Fehler im Signal zu erkennen. In ähnlicher Weise enthalten Audio-CDs viele redundante Informationen, sodass sie auch dann noch perfekt abgespielt werden können, wenn sie zerkratzt sind. Verstößt das gegen das DRY-Prinzip? Wahrscheinlich, aber so erhalten Sie Zuverlässigkeit.

Es gibt noch eine andere Sichtweise:

Ihr Test ist die maßgebliche Antwort. Der Code, den es testet, wird nur automatisch von Ihnen, dem Code-Affen, generiert. Wenn wir Code basierend auf Komponententests automatisch generieren könnten (wie wir Datenzugriffsschichten basierend auf einem Datenbankschema automatisch generieren würden), würden wir nicht gegen das DRY-Prinzip (oder zumindest nicht gegen das OAOO-Prinzip) verstoßen.

Scott Whitlock
quelle
3

Wenn Sie jedoch Tests für Code schreiben, beschreiben Sie das erwartete Verhalten für das System zweimal (einmal im Code und einmal im Test).

Nicht ganz. Der Code ist nicht die Beschreibung des erwarteten Verhaltens, sondern dessen Implementierung . Was Fehler enthalten kann, deshalb brauchen wir die Tests.

Die Implementierung eines relativ einfachen Algorithmus oder einer Abstraktion ist viel schwieriger als die Beschreibung. Jeder anständige Programmierer kann in wenigen Sätzen beschreiben, wie die binäre Suche funktioniert - dennoch berichtete Jon Bentley, dass in seinen Experimenten über 70% der erfahrenen Programmierer, die an seinem Kurs teilnahmen, diese nicht korrekt implementiert haben.

Deshalb brauchen wir Unit-Tests. Niemand arbeitet gerne doppelt so viel, um die gleichen Ergebnisse zu erzielen, aber all jene Entwickler, die diese Praxis formuliert und evangelisiert haben, haben aus ihrer eigenen hart erarbeiteten Erfahrung erkannt, dass sie sie brauchen. Es waren clevere Leute, die Software so schnell wie möglich entwickeln wollten - was erfordert, dass alle doppelten und nutzlosen Aufgaben aus dem Entwicklungsprozess entfernt werden. Unit-Tests sind keine Doppelarbeit.

Péter Török
quelle