Suche…


Einführung

Beim Start mit Unit-Testing tauchen alle möglichen Fragen auf:

Was ist Unit-Testing? Was ist ein SetUp und TearDown? Wie gehe ich mit Abhängigkeiten um? Warum überhaupt Unit-Testing? Wie mache ich gute Komponententests?

In diesem Artikel werden alle diese Fragen beantwortet, sodass Sie mit Unit-Tests in jeder gewünschten Sprache beginnen können.

Bemerkungen

Was ist Unit-Test?

Unit-Tests sind das Testen von Code, um sicherzustellen, dass er die Aufgabe ausführt, die er ausführen soll. Es testet Code auf einer möglichst niedrigen Ebene - den individuellen Methoden Ihrer Klassen.

Was ist eine Einheit?

Jedes diskrete Codemodul, das isoliert getestet werden kann. Die meisten Zeitklassen und ihre Methoden. Diese Klasse wird im Allgemeinen als "Class Under Test" (CUT) oder "System Under Test" (SUT) bezeichnet.

Der Unterschied zwischen Unit-Tests und Integrationstests

Komponententest ist der Vorgang, bei dem eine einzelne Klasse unabhängig von ihren tatsächlichen Abhängigkeiten getestet wird. Integrationstests sind das Testen einer einzelnen Klasse zusammen mit einer oder mehreren ihrer tatsächlichen Abhängigkeiten.

Das SetUp und TearDown

Wenn die SetUp-Methode erstellt ist, wird sie vor jedem Komponententest und TearDown nach jedem Test ausgeführt.

Im Allgemeinen fügen Sie alle erforderlichen Schritte in SetUp und alle Bereinigungsschritte in TearDown hinzu. Sie erstellen diese Methode jedoch nur, wenn diese Schritte für jeden Test erforderlich sind. Wenn nicht, werden diese Schritte innerhalb der spezifischen Tests im Abschnitt "Anordnen" ausgeführt.

Umgang mit Abhängigkeiten

Oftmals hängt eine Klasse von anderen Klassen ab, um ihre Methoden auszuführen. Um sich nicht auf diese anderen Klassen verlassen zu können, müssen Sie diese fälschen. Sie können diese Klassen selbst erstellen oder ein Isolations- oder Mockup-Framework verwenden. Ein Isolationsframework ist eine Sammlung von Code, mit der gefälschte Klassen einfach erstellt werden können.

Gefälschte Kurse

Jede Klasse, die über ausreichend Funktionalität verfügt, um vorzugeben, dass es sich um eine Abhängigkeit handelt, die von einer CUT benötigt wird. Es gibt zwei Arten von Fälschungen: Stubs und Mocks.

  • Ein Stub: Eine Fälschung, die keine Auswirkung auf das Bestehen oder Nichtbestehen des Tests hat und die nur existiert, um den Test auszuführen.
  • Ein Mock: Eine Fälschung, die das Verhalten der CUT verfolgt und den Test aufgrund dieses Verhaltens besteht oder nicht besteht.

Warum Unit-Tests durchführen?

1. Unit-Tests werden Fehler finden

Wenn Sie eine vollständige Testreihe schreiben, die das erwartete Verhalten für eine bestimmte Klasse definiert, wird alles angezeigt, was sich nicht wie erwartet verhält.

2. Unit-Tests halten Fehler fern

Nehmen Sie eine Änderung vor, die einen Fehler einführt, und Ihre Tests können ihn schon beim nächsten Ausführen Ihrer Tests aufdecken.

3. Gerätetests sparen Zeit

Durch das Schreiben von Komponententests können Sie sicherstellen, dass Ihr Code von Anfang an wie geplant funktioniert. Unit-Tests definieren, was Ihr Code tun soll, und Sie werden keine Zeit damit verbringen, Code zu schreiben, der Dinge tut, die er nicht tun sollte. Niemand überprüft im Code, dass er nicht glaubt, dass er funktioniert, und Sie müssen etwas tun, damit Sie glauben, dass es funktioniert. Verbringen Sie diese Zeit, um Komponententests zu schreiben.

4. Unit-Tests geben Sicherheit

Sie können all diese Tests ausführen und wissen, dass Ihr Code wie erwartet funktioniert. Es ist eine sehr gute Sache, den Status Ihres Codes zu kennen, dass er funktioniert und dass Sie ihn ohne Angst umstellen und verbessern können.

5. Unit-Tests dokumentieren die ordnungsgemäße Verwendung einer Klasse

Komponententests sind einfache Beispiele dafür, wie Ihr Code funktioniert, was er tun soll und wie Sie den getesteten Code richtig verwenden.

Allgemeine Regeln für Komponententests

1. Befolgen Sie für den Aufbau eines Komponententests die AAA-Regel

Ordnen:

Richten Sie das zu testende Ding ein. Wie Variablen, Felder und Eigenschaften, um den Test sowie das erwartete Ergebnis auszuführen.

Act: Rufen Sie tatsächlich die Methode auf, die Sie testen

Behaupten:

Rufen Sie das Testframework auf, um zu überprüfen, ob das Ergebnis Ihrer "Aktion" das ist, was erwartet wurde.

2. Testen Sie eine Sache zur Zeit isoliert

Alle Klassen sollten isoliert getestet werden. Sie sollten sich nicht auf etwas anderes als die Spötter und Stummel verlassen. Sie sollten sich nicht auf die Ergebnisse anderer Tests verlassen.

3. Schreiben Sie zuerst einfache Tests in die Mitte

Die ersten Tests, die Sie schreiben, sollten die einfachsten Tests sein. Sie sollten die sein, die die Funktionalität, die Sie schreiben möchten, im Grunde und auf einfache Weise veranschaulicht. Sobald diese Tests bestanden sind, sollten Sie mit dem Schreiben der komplizierteren Tests beginnen, die die Kanten und Grenzen Ihres Codes testen.

4. Schreiben Sie Tests, die die Kanten testen

Nachdem Sie die Grundlagen getestet haben und wissen, dass Ihre Basisfunktionen funktionieren, sollten Sie die Kanten testen. Eine gute Reihe von Tests untersucht die äußeren Ränder der möglichen Methode.

Zum Beispiel:

  • Was passiert bei Überlauf?
  • Was ist, wenn die Werte auf Null oder darunter gehen?
  • Was ist, wenn sie zu MaxInt oder MinInt gehen?
  • Was ist, wenn Sie einen Bogen von 361 Grad erstellen?
  • Was passiert, wenn Sie eine leere Zeichenfolge übergeben?
  • Was passiert, wenn eine Zeichenfolge 2 GB groß ist?

5. Testen Sie über Grenzen hinweg

Unit-Tests sollten beide Seiten einer bestimmten Grenze testen. Wenn Sie sich über Grenzen hinweg bewegen, gibt es Bereiche, an denen der Code möglicherweise nicht funktioniert oder auf unvorhersehbare Weise funktioniert.

6. Wenn möglich, testen Sie das gesamte Spektrum

Wenn es praktisch ist, testen Sie die gesamten Möglichkeiten für Ihre Funktionalität. Wenn es sich um einen Aufzählungstyp handelt, testen Sie die Funktionalität mit jedem der Elemente in der Aufzählung. Es kann unpraktisch sein, jede Möglichkeit zu testen, aber wenn Sie jede Möglichkeit testen können, tun Sie es.

7. Decken Sie nach Möglichkeit jeden Codepfad ab

Dies ist ebenfalls eine Herausforderung, aber wenn Ihr Code zum Testen vorgesehen ist und Sie ein Code Coverage-Tool verwenden, können Sie sicherstellen, dass jede Zeile Ihres Codes mindestens einmal durch Komponententests abgedeckt wird. Wenn Sie jeden Codepfad abdecken, kann dies nicht garantieren, dass keine Fehler vorhanden sind. Sie erhalten jedoch wertvolle Informationen zum Status jeder Codezeile.

8. Schreiben Sie Tests, die einen Fehler enthüllen, und beheben Sie ihn dann

Wenn Sie einen Fehler finden, schreiben Sie einen Test, der ihn aufdeckt. Dann können Sie den Fehler leicht beheben, indem Sie den Test debuggen. Dann haben Sie einen schönen Regressionstest, um sicherzustellen, dass der Fehler sofort erkannt wird, wenn der Fehler aus irgendeinem Grund zurückkommt. Es ist wirklich einfach, einen Fehler zu beheben, wenn Sie einen einfachen, direkten Test im Debugger haben.

Ein Nebeneffekt hier ist, dass Sie Ihren Test getestet haben. Da Sie gesehen haben, dass der Test fehlgeschlagen ist und wenn Sie gesehen haben, dass der Test erfolgreich ist, wissen Sie, dass der Test gültig ist, da er sich als richtig erwiesen hat. Dies macht es zu einem noch besseren Regressionstest.

9. Machen Sie jeden Test unabhängig voneinander

Tests sollten niemals voneinander abhängen. Wenn Ihre Tests in einer bestimmten Reihenfolge ablaufen müssen, müssen Sie die Tests ändern.

10. Schreiben Sie einen Test pro Test

Sie sollten einen Test pro Test schreiben. Wenn Sie dies nicht tun können, refraktorieren Sie Ihren Code, sodass die SetUp- und TearDown-Ereignisse zum korrekten Erstellen der Umgebung verwendet werden, sodass jeder Test einzeln ausgeführt werden kann.

11. Benennen Sie Ihre Tests eindeutig. Fürchte dich nicht vor langen Namen

Da Sie eine Prüfung pro Test durchführen, kann jeder Test sehr spezifisch sein. Scheuen Sie sich also nicht, lange, vollständige Testnamen zu verwenden.

Ein langer vollständiger Name informiert Sie sofort darüber, welcher Test fehlgeschlagen ist und was genau der Test versucht hat.

Lange, klar benannte Tests können Ihre Tests auch dokumentieren. Ein Test mit dem Namen "DividedByZeroShouldThrowException" dokumentiert genau, was der Code tut, wenn Sie versuchen, durch Null zu teilen.

12. Testen Sie, dass jede angehobene Ausnahme tatsächlich ausgelöst wird

Wenn Ihr Code eine Ausnahme auslöst, schreiben Sie einen Test, um sicherzustellen, dass jede Ausnahme, die Sie auslösen, tatsächlich ausgelöst wird, wenn sie beabsichtigt ist.

13. Vermeiden Sie die Verwendung von CheckTrue oder Assert.IsTrue

Vermeiden Sie die Prüfung auf einen booleschen Zustand. Wenn Sie beispielsweise prüfen, ob zwei Dinge mit CheckTrue oder Assert.IsTrue übereinstimmen, verwenden Sie stattdessen CheckEquals oder Assert.IsEqual. Warum? Deswegen:

CheckTrue (Expected, Actual) Dies wird in etwa Folgendes berichten: "Einige Tests sind fehlgeschlagen: Erwartete war wahr, aber das tatsächliche Ergebnis war False."

Das sagt dir nichts.

CheckEquals (Voraussichtlich, Ist)

Dies sagt Ihnen etwas wie: "Einige Tests sind fehlgeschlagen: Erwartete 7, aber das tatsächliche Ergebnis war 3."

Verwenden Sie CheckTrue oder Assert.IsTrue nur, wenn Ihr erwarteter Wert tatsächlich eine boolesche Bedingung ist.

14. Führen Sie ständig Ihre Tests durch

Führen Sie Ihre Tests aus, während Sie Code schreiben. Ihre Tests sollten schnell ablaufen, sodass Sie sie auch nach geringfügigen Änderungen ausführen können. Wenn Sie Ihre Tests nicht als Teil Ihres normalen Entwicklungsprozesses ausführen können, läuft etwas schief. Unit-Tests sollen fast sofort ablaufen. Wenn dies nicht der Fall ist, liegt dies wahrscheinlich daran, dass Sie sie nicht isoliert ausführen.

15. Führen Sie Ihre Tests als Teil jedes automatisierten Builds aus

So wie Sie einen Test während der Entwicklung ausführen sollten, sollten sie auch ein integraler Bestandteil Ihres kontinuierlichen Integrationsprozesses sein. Ein fehlgeschlagener Test sollte bedeuten, dass Ihr Build defekt ist. Lassen Sie die fehlgeschlagenen Tests nicht verweilen. Betrachten Sie es als Build-Fehler und beheben Sie es sofort.

Beispiel für einen einfachen Komponententest in C #

In diesem Beispiel testen wir die Summenmethode eines einfachen Rechners.

In diesem Beispiel testen wir die Anwendung: ApplicationToTest. Dieser hat eine Klasse namens Calc. Diese Klasse hat eine Methode Sum ().

Die Methode Sum () sieht folgendermaßen aus:

public void Sum(int a, int b)
{
    return a + b;
}

Der Komponententest zum Testen dieser Methode sieht folgendermaßen aus:

[Testclass]
public class UnitTest1
{
    [TestMethod]
    public void TestMethod1()
    {
        //Arrange
        ApplicationToTest.Calc ClassCalc = new ApplicationToTest.Calc();
        int expectedResult = 5;

        //Act
        int result = ClassCalc.Sum(2,3);

        //Assert
        Assert.AreEqual(expectedResult, result);
    }
}


Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow