it-swarm.com.de

Unit-Test mehrerer Bedingungen in einer IF-Anweisung

Ich habe einen Codeabschnitt, der ungefähr so ​​aussieht:

function bool PassesBusinessRules()
{
    bool meetsBusinessRules = false;

    if (PassesBusinessRule1 
         && PassesBusinessRule2
         && PassesBusinessRule3)
    {
         meetsBusinessRules= true;
    }

    return meetsBusinessRules;
}

Ich glaube, es sollte vier Unit-Tests für diese spezielle Funktion geben. Drei, um jede der Bedingungen in der if-Anweisung zu testen und sicherzustellen, dass sie false zurückgibt. Und ein weiterer Test, der sicherstellt, dass die Funktion true zurückgibt.

Frage : Sollte es stattdessen tatsächlich zehn Unit-Tests geben? Neun, die jeden der möglichen Fehlerpfade überprüfen. IE:

  • Falsch Falsch Falsch
  • Falsch Falsch Richtig
  • Falsch Richtig Falsch

Und so weiter für jede mögliche Kombination.

Ich denke, das ist übertrieben, aber einige der anderen Mitglieder meines Teams tun dies nicht. Wenn BusinessRule1 ausfällt, sollte es immer false zurückgeben. Es spielt keine Rolle, ob es zuerst oder zuletzt überprüft wurde.

28
bwalk2895

Formal haben diese Arten der Berichterstattung Namen.

Erstens gibt es Prädikatabdeckung: Sie möchten einen Testfall haben, der die if-Anweisung wahr macht, und einen, der sie falsch macht. Die Erfüllung dieser Abdeckung ist wahrscheinlich eine Grundvoraussetzung für eine gute Testsuite.

Dann gibt es Condition Coverage: Hier möchten Sie testen, ob jede Unterbedingung im if den Wert true und false hat. Dies führt natürlich zu mehr Tests, fängt jedoch normalerweise mehr Fehler ab. Daher ist es oft eine gute Idee, diese in Ihre Testsuite aufzunehmen, wenn Sie Zeit haben.

Die am weitesten fortgeschrittenen Abdeckungskriterien werden normalerweise Combinatorial Condition Coverage genannt: Hier besteht das Ziel darin, einen Testfall zu haben, der alle möglichen Kombinationen von Booleschen Werten in Ihrem Test durchläuft.

Ist dies besser als eine einfache Prädikat- oder Bedingungsabdeckung? In Bezug auf die Abdeckung natürlich. Aber es ist nicht kostenlos. Die Kosten für die Testwartung sind sehr hoch. Aus diesem Grund kümmern sich die meisten Menschen nicht um eine vollständige kombinatorische Abdeckung. Normalerweise ist das Testen aller Zweige (oder aller Bedingungen) gut genug, um Fehler zu erkennen. Das Hinzufügen der zusätzlichen Tests für kombinatorische Tests führt normalerweise nicht zu weiteren Fehlern, erfordert jedoch viel Aufwand beim Erstellen und Verwalten. Der zusätzliche Aufwand macht dies normalerweise nicht die sehr sehr kleine Auszahlung wert, daher würde ich dies nicht empfehlen.

Ein Teil dieser Entscheidung sollte darauf basieren, wie riskant Sie denken, dass Code sein wird. Wenn es viel Raum zum Scheitern gibt, lohnt es sich zu testen. Wenn es etwas stabil ist und sich nicht viel ändert, sollten Sie Ihre Testbemühungen auf andere Bereiche konzentrieren.

32
Oleksi

Letztendlich hängt es von Ihnen (r Team), dem Code und der spezifischen Projektumgebung ab. Es gibt keine universelle Regel. Sie (r Team) sollten schreiben Sie so viele Tests, wie Sie brauchen, um sich sicher zu fühlen, dass der Code tatsächlich korrekt ist. Wenn Ihre Teamkollegen nicht von 4 Tests überzeugt sind, brauchen Sie vielleicht mehr.

Die OTOH-Zeit zum Schreiben von Komponententests ist normalerweise eine knappe Ressource. Also bemühen Sie sich, den besten Weg zu finden, um die begrenzte Zeit zu verbringen, die Sie haben. Z.B. Wenn Sie eine andere wichtige Methode mit einer Abdeckung von 0% haben, ist es möglicherweise besser, ein paar Komponententests zu schreiben, um diese abzudecken, als zusätzliche Tests für diese Methode hinzuzufügen. Natürlich hängt es auch davon ab, wie fragil die Implementierung jedes einzelnen ist. Die Planung vieler Änderungen an dieser bestimmten Methode in absehbarer Zeit kann eine zusätzliche Abdeckung durch Unit-Tests rechtfertigen. Dies kann sich auf einem kritischen Pfad innerhalb des Programms befinden. Dies sind alles Faktoren, die nur Sie (Ihr Team) beurteilen können.

Ich persönlich würde normalerweise mit den 4 Tests, die Sie skizzieren, zufrieden sein, das heißt:

  • wahr falsch falsch
  • falsch wahr falsch
  • falsch falsch wahr
  • wahr wahr wahr wahr

plus vielleicht eins:

  • wahr wahr falsch

um sicherzustellen, dass der einzige Weg, einen Rückgabewert von true zu erhalten, darin besteht, alle drei Geschäftsregeln zu erfüllen. Aber am Ende, wenn Ihre Teamkollegen darauf bestehen, kombinatorische Pfade abzudecken, kann es billiger sein, diese zusätzlichen Tests hinzuzufügen, als das Argument viel länger fortzusetzen :-)

9
Péter Török

Wenn Sie sicher sein möchten, benötigen Sie acht Komponententests unter Verwendung der Bedingungen, die durch eine Tabelle mit drei variablen Wahrheiten dargestellt werden ( http://teach.valdosta.edu/plmoch/MATH4161/Spring%202004/and_or_if_files/image006). gif ).

Sie können nie sicher sein, dass die Geschäftslogik immer vorschreibt, dass die Überprüfungen in dieser Reihenfolge durchgeführt werden, und Sie möchten, dass der Test so wenig wie möglich über die tatsächliche Implementierung weiß.

3
smp7d

Ja, in einer idealen Welt sollte es die volle Kombination geben.

Wenn Sie den Unit-Test durchführen, sollten Sie wirklich versuchen, wie zu ignorieren. Die Methode erledigt ihre Arbeit. Stellen Sie einfach die 3 Eingänge bereit und überprüfen Sie, ob der Ausgang korrekt ist.

2
Telastyn

Staat ist böse. Die folgende Funktion benötigt keinen Komponententest, da sie keine Nebenwirkungen hat und genau bekannt ist, was sie tut und was nicht. Warum es testen? Vertraust du nicht deinem eigenen Gehirn ??? Statische Funktionen sind großartig!

static function bool Foo(bool a, bool b, bool c)
{
    return a && b && c;
}
1
Job

Ich weiß, dass diese Frage ziemlich alt ist. Aber ich möchte dem Problem eine andere Perspektive geben.

Erstens sollten Ihre Komponententests zwei Zwecke haben:

  1. Erstellen Sie eine Dokumentation für Sie und Ihre Teamkollegen, damit Sie nach einer bestimmten Zeit den Komponententest lesen und sicherstellen können, dass Sie what's the class' intention Und how the class is doing its work Verstehen.
  2. Während der Entwicklung stellt der Komponententest sicher, dass der Code, den wir aufschreiben, seine Arbeit so macht, wie es in unserem Kopf beabsichtigt war.

Um das Problem zusammenzufassen, wollen wir einen complex if statement Testen. Für das gegebene Beispiel gibt es 2 ^ 3 Möglichkeiten, das ist eine wichtige Anzahl von Tests, die wir schreiben können.

  • Sie können sich an diese Tatsache anpassen und 8 Tests aufschreiben oder parametrisierte Tests verwenden
  • Sie können auch den anderen Antworten folgen und sich daran erinnern, dass die Tests mit der Absicht klar sein sollten. Auf diese Weise werden wir nicht mit zu vielen Details herumspielen, die in naher Zukunft möglicherweise schwieriger zu verstehen sind what is doing the code

Wenn Sie jedoch in der Lage sind, Ihre Tests noch komplexer als die Implementierung zu gestalten, sollte die Implementierung (je nach Fall mehr oder weniger) neu gestaltet werden und nicht der Test selbst.

Für die komplexen if-Anweisungen könnten Sie beispielsweise an Kettenverantwortungsmuster denken und jeden Handler folgendermaßen implementieren:

If some simple business rule apply, derive to the next handler

Wie einfach wäre es, verschiedene einfache Regeln anstelle einer komplexen Regel zu testen?

Ich hoffe es hilft,

1
cnexans

Dies ist einer der Fälle, in denen so etwas wie Quickcheck ( http://en.wikipedia.org/wiki/QuickCheck ) Ihr Freund sein wird. Anstatt alle N Fälle von Hand aufzuschreiben, muss der Computer alle (oder zumindest eine große Anzahl) möglicher Testfälle generieren und überprüfen, ob alle ein vernünftiges Ergebnis liefern.

Wir programmieren hier Computer für den Lebensunterhalt. Warum programmieren Sie den Computer nicht so, dass er Ihre Testfälle für Sie generiert?

0
Zachary K

Sie könnten die Bedingungen in Wachbedingungen umgestalten:

if (! PassesBusinessRule1) {
    return false;
}

if (! PassesBusinessRule2) {
    return false;
}

if (! PassesBusinessRule3) {
    return false;
}

Ich denke nicht, dass dies die Anzahl der Fälle verringert, aber meiner Erfahrung nach ist es einfacher, sie auf diese Weise auszubrechen.

(Beachten Sie, dass ich ein großer "Single Point of Exit" -Lüfter bin, aber eine Ausnahme für die Schutzbedingungen mache. Es gibt jedoch auch andere Möglichkeiten, den Code so zu strukturieren, dass Sie keine separaten Rückgaben haben.)

0
Rob