Unit Testing: "Es ist ein Code-Geruch, wenn Sie umgestalten und es keine Mitarbeiter gibt"?


9

Ich lese The Art of Unit Testing von Roy Osherove. Ich bin in Abschnitt 7.2 und schreibe wartbare Tests, in denen der Autor diesen Hinweis zum Codegeruch hat:

HINWEIS: Wenn Sie den internen Status so umgestalten, dass er für einen externen Test sichtbar ist, kann dies als Codegeruch angesehen werden (ein Zeichen dafür, dass möglicherweise etwas im Design oder in der Logik des Codes nicht stimmt)? Es ist kein Codegeruch, wenn Sie umgestalten, um Mitarbeiter freizulegen. Es ist ein Code-Geruch, wenn Sie ein Refactoring durchführen und keine Mitarbeiter vorhanden sind (Sie müssen also nichts stummeln oder verspotten).

EDIT : Was der Autor unter "Kollaborateuren" versteht, sind Abhängigkeiten. Einige seiner Beispiele für Abhängigkeiten sind Klassen, die auf eine Datenbank oder auf das Dateisystem des Betriebssystems zugreifen. Hier definiert er Stub und beginnt, das Wort Kollaborateur zu verwenden:

Ein Stub ist ein steuerbarer Ersatz für eine vorhandene Abhängigkeit (oder einen Mitarbeiter ) im System.

Der Autor hat kein Beispiel für diesen Codegeruch und ich habe Probleme zu verstehen / mir vorzustellen, wie dies aussehen würde. Kann jemand dies etwas näher erläutern und vielleicht ein konkretes Beispiel geben?


Ich denke, die Verwirrung hier rührt vom Wort "Kollaborateure" her. Ich muss zugeben, ich bin mir auch nicht sicher, was er in diesem Zusammenhang meint.
Wikipedia

@ Bryan Ross, ich habe den Beitrag dahingehend aktualisiert, wie der Autor das Wort "Mitarbeiter" verwendet. Vielen Dank!
Programmierer

Antworten:


3

Ich denke, das ist es, worauf der Autor abzielt.

In meinem Codebeispiel habe ich ein Zeitfenster, das eine Ausgabemenge plus eine Start- und Stoppzeit verwendet. Es ist beabsichtigt, ein Ausgabefenster über einen Zeitraum von 24 Stunden zu zeichnen. Eine Falte wird hinzugefügt, wenn die Startzeit größer als die Stoppzeit ist, da dies ein Zeitfenster ist, das sich über Mitternacht erstreckt.

Sie können Komponententests schreiben, die das Objekt vollständig ausführen, ohne die privaten Variablen verfügbar zu machen. Diese privaten Bools und Zeitspannen sind die Mitarbeiter, auf die er sich bezieht, wenn er die Interna für Unit-Tests freigibt. Laut dem Buch wäre das Aufdecken dieser Interna KEIN Code-Geruch, da sie Kollaborateure sind.

Das Aufdecken des Doppelten outputwäre ein Codegeruch, da es kein Kollaborateur ist - es ist ein Element, das explizit von der Klasse selbst verborgen wird und eine bedingte Logik enthält GetOutput, um zu bestimmen, was zurückgegeben werden soll.

Das Eingraben in die Bools / Zeitspannen würde die Unit-Tests umfassender machen. Er sagt, das ist gut.
Das Eintauchen in das Doppelte outputwürde zusätzliche Logik in Ihrem Komponententest erfordern, die die Aktivitäten widerspiegelt GetOutput. Dies wäre der Code-Geruch, auf den er sich bezieht.

öffentliche Klasse TimeWindow
{
  private bool isConst;
  private bool spansMidnight;
  private TimeSpan start1;
  private TimeSpan stop1;
  private TimeSpan start2;
  private TimeSpan stop2;
  private Doppelausgabe;

  öffentliches TimeWindow (Double Out, TimeSpan-Start, TimeSpan-Stopp)
  {
    Ausgabe = aus;

    if (start == stop)
      isConst = true;
    sonst wenn (start> stop)
    {
      spansMidnight = true;
      start1 = Mitternacht;
      stop1 = stop;
      start2 = start;
      stop2 = Mitternacht;
    }}
    sonst 
    {
      start1 = start;
      stop1 = stop;
    }}
  }}

  public double GetOutput (TimeSpan-Zeit)
  {
    // hier eine Logik darüber, was / wie zurückgegeben werden soll
    ...
    Ausgabe zurückgeben;
  }}

}}

0

Angenommen, wir haben eine Domänenklasse, und diese Domänenklasse verfügt über direkte Kenntnisse der Persistenzschicht mithilfe eines Repositorys, das sie verwendet, um eine "Save" -Methode auf Instanzebene verfügbar zu machen, die Objekte, die an der Domänenklasse arbeiten, aufrufen können, um Änderungen beizubehalten gemacht, ohne Kenntnis des Mechanismus zu benötigen (ob dies "gutes" Design ist, ist eine Diskussion für einen anderen Tag). Das Refactoring der Klasse, um dieses Repository als Eigenschafts- und / oder Konstruktorargument verfügbar zu machen, wodurch die Übergabe eines verspotteten Repositorys ermöglicht wird, das sicherstellen kann, dass der richtige Aufruf erfolgt, ist in der Regel nicht nur zum Testen, sondern auch zur allgemeinen Wartbarkeit eine gute Sache.

Da es sich um eine Domänenklasse handelt, enthält sie Statusdaten. Nehmen wir für einen Moment an, dass eine der statusbehafteten Eigenschaften ein Hintergrundfeld hat und die Eigenschaftszugriffsprüfer testen, ob eine neue Eingabe basierend auf der aktuellen gültig ist (möglicherweise kann der neue Wert niemals kleiner sein als der alte). Sie müssen diese Validierung testen, müssen jedoch auf das Hintergrundfeld zugreifen, um einen Anfangswert festzulegen, den Sie dann überschreiben möchten. Dies sollte eine rote Fahne sein; Wenn der Test Zugriff auf das Hintergrundfeld benötigt (dies ist ein Implementierungsdetail, sollte kein Verbraucher dies jemals tunmüssen wissen, dass es da ist), um das Objekt für einen Test in einen konsistenten Zustand zu bringen. Wie würde dann Produktionscode ein konsistentes Objekt erhalten? Wenn es eine Methode gibt, mit der Produktionscode dasselbe tut wie Ihr Test, sollte der Test wahrscheinlich auf diese Weise nachahmen. Wenn es keine gültige Möglichkeit für Produktionscode gibt, das Objekt in diesen Zustand zu versetzen, warum testen Sie dann dieses Szenario?

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.