Freigeben über


Erstellen und Ausführen von Komponententests für .NET

Dieser Artikel führt Sie durch das Erstellen, Ausführen und Anpassen einer Reihe von Komponententests mithilfe des Microsoft-Komponententestframeworks für verwalteten Code und Visual Studio Test Explorer. Sie beginnen mit einem C#-Projekt, das sich in der Entwicklung befindet, erstellen Tests, die den Code testen, führen die Tests aus und untersuchen die Ergebnisse. Anschließend ändern Sie den Projektcode, und führen Sie die Tests erneut aus. Wenn Sie einen konzeptionellen Überblick über diese Aufgaben wünschen, bevor Sie diese Schritte ausführen, lesen Sie Komponententestgrundlagen.

In diesem Artikel wird beschrieben, wie Sie Komponententests manuell erstellen. Wenn Sie Tests automatisch aus vorhandenem Code generieren möchten, lesen Sie die folgenden Artikel:

Voraussetzungen

Visual Studio muss zusammen mit der .NET-Desktop-Entwicklungs-Workload installiert werden.

Erstellen eines zu testenden Projekts

  1. Öffnen Sie Visual Studio.

  2. Wählen Sie im Startfenster Neues Projekt erstellenaus.

  3. Suchen und wählen Sie die Projektvorlage "C# Konsolen-App für .NET" aus, und klicken Sie dann auf Weiter.

    Wenn die Konsolen-App-Vorlage nicht angezeigt wird, verwenden Sie den Visual Studio Installer, um die .NET-Desktopentwicklungs-Arbeitsauslastung zu installieren.

  4. Geben Sie dem Projekt den Namen Bank, und klicken Sie dann auf Weiter.

  5. Wählen Sie entweder das empfohlene Zielframework oder .NET 8 aus, und wählen Sie dann Createaus.

    Das Bankprojekt wird im Projektmappen-Explorer erstellt und angezeigt, wobei die Program.cs Datei im Code-Editor geöffnet ist.

    Anmerkung

    Wenn Program.cs nicht im Editor geöffnet ist, doppelklicken Sie auf die Datei Program.cs im Projektmappen-Explorer, um sie zu öffnen.

  6. Ersetzen Sie den Inhalt von Program.cs durch den folgenden C#-Code, der eine Klasse definiert, BankAccount:

    using System;
    
    namespace BankAccountNS
    {
        /// <summary>
        /// Bank account demo class.
        /// </summary>
        public class BankAccount
        {
            private readonly string m_customerName;
            private double m_balance;
    
            private BankAccount() { }
    
            public BankAccount(string customerName, double balance)
            {
                m_customerName = customerName;
                m_balance = balance;
            }
    
            public string CustomerName
            {
                get { return m_customerName; }
            }
    
            public double Balance
            {
                get { return m_balance; }
            }
    
            public void Debit(double amount)
            {
                if (amount > m_balance)
                {
                    throw new ArgumentOutOfRangeException("amount");
                }
    
                if (amount < 0)
                {
                    throw new ArgumentOutOfRangeException("amount");
                }
    
                m_balance += amount; // intentionally incorrect code
            }
    
            public void Credit(double amount)
            {
                if (amount < 0)
                {
                    throw new ArgumentOutOfRangeException("amount");
                }
    
                m_balance += amount;
            }
    
            public static void Main()
            {
                BankAccount ba = new BankAccount("Mr. Bryan Walton", 11.99);
    
                ba.Credit(5.77);
                ba.Debit(11.22);
                Console.WriteLine("Current balance is ${0}", ba.Balance);
            }
        }
    }
    
  7. Ändern Sie den Dateinamen per Rechtsklick in BankAccount.cs, und klicken Sie im Projektmappen-Explorer auf Umbenennen.

  8. Wählen Sie im Menü Erstellen die Option Projektmappe erstellen aus, oder drücken Sie STRG + UMSCHALT + B.

Sie haben jetzt ein Projekt mit Methoden, die Sie testen können. In diesem Artikel konzentrieren sich die Tests auf die Debit-Methode. Die Debit Methode wird aufgerufen, wenn Geld von einem Konto zurückgezogen wird.

Erstellen eines Komponententestprojekts

  1. Klicken Sie im Menü Datei auf Hinzufügen>Neues Projekt.

    Tipp

    Sie können auch mit der rechten Maustaste auf die Lösung im Projektmappen-Explorer klicken und Hinzufügen>Neues Projektauswählen.

  2. Geben Sie Test- in das Suchfeld ein, wählen Sie C#- als Sprache aus, und wählen Sie dann die C#-MSTest Test Project für .NET-Vorlage aus, und klicken Sie dann auf Weiter.

    Anmerkung

    In Visual Studio 2019, Version 16.9, ist die MSTest-Projektvorlage Unit Test Project.

  3. Geben Sie dem Projekt den Namen BankTests, und klicken Sie auf Weiter.

  4. Wählen Sie entweder das empfohlene Zielframework oder .NET 8 aus, und wählen Sie dann Createaus.

    Ab Visual Studio 2022, Version 17.10, können Sie auch einen Testläufer auswählen. Für den Testläufer können Sie entweder VSTest- oder MSTest-auswählen. Weitere Informationen zu den Unterschieden zwischen Testrunnern finden Sie unter Vergleich zwischen „Microsoft.Testing.Platform“ und „VSTest“.

    Das BankTests Projekt wird der Bank Lösung hinzugefügt.

  5. Fügen Sie im projekt BankTests einen Verweis auf das projekt Bank hinzu.

    Wählen Sie im Projektmappen-Explorer im Projekt BankTests zunächst Abhängigkeiten und dann im Kontextmenü Verweis hinzufügen (oder Projektverweis hinzufügen) aus.

  6. Erweitern Sie im Dialogfeld Verweis-Manager die Option Projekte, wählen Sie Projektmappe aus, und überprüfen Sie das Element Bank.

  7. Wählen Sie OKaus.

Erstellen der Testklasse

Erstellen Sie eine Testklasse, um die BankAccount Klasse zu überprüfen. Sie können die UnitTest1.cs Datei verwenden, die von der Projektvorlage generiert wurde, aber geben Sie der Datei und klasse aussagekräftigere Namen.

Umbenennen einer Datei und Klasse

  1. Um die Datei umzubenennen, wählen Sie im Projektmappen-Explorerdie UnitTest1.cs Datei im Projekt BankTests aus. Wählen Sie im Kontextmenü die Option Umbenennen aus (alternativ F2 drücken), und ändern Sie dann den Namen der Datei in BankAccountTests.cs.

  2. Um die Klasse umzubenennen, positionieren Sie den Cursor auf UnitTest1 im Code-Editor, klicken Sie mit der rechten Maustaste, und wählen Sie dann Umbenennen aus (oder drücken Sie F2). Geben Sie BankAccountTests ein, und drücken Sie dann die EINGABETASTE.

Die datei BankAccountTests.cs enthält jetzt den folgenden Code:

// The 'using' statement for Test Tools is in GlobalUsings.cs
// using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace BankTests
{
    [TestClass]
    public class BankAccountTests
    {
        [TestMethod]
        public void TestMethod1()
        {
        }
    }
}

Hinzufügen einer using-Anweisung

Fügen Sie der Testklasse eine using-Anweisung hinzu, damit Sie das Testprojekt ohne vollqualifizierte Namen aufrufen können. Fügen Sie oben in der Klassendatei Folgendes hinzu:

using BankAccountNS;

Testklassenanforderungen

Die Mindestanforderungen für eine Testklasse sind:

  • Das attribut [TestClass] ist für jede Klasse erforderlich, die Komponententestmethoden enthält, die Sie im Test-Explorer ausführen möchten.

  • Jede Testmethode, die vom Test-Explorer erkannt werden soll, muss das attribut [TestMethod] aufweisen.

Sie können andere Klassen in einem Komponententestprojekt haben, das nicht über das attribut [TestClass] verfügt, und Sie können andere Methoden in Testklassen verwenden, die nicht über das attribut [TestMethod] verfügen. Sie können diese anderen Klassen und Methoden aus Ihren Testmethoden aufrufen.

Erstellen der ersten Testmethode

In diesem Verfahren schreiben Sie Komponententestmethoden, um das Verhalten der Debit Methode der BankAccount Klasse zu überprüfen.

Es gibt mindestens drei Verhaltensweisen, die überprüft werden müssen:

  • Die Methode löst eine ArgumentOutOfRangeException aus, wenn der Lastbetrag größer als der Saldo ist.

  • Die Methode löst eine ArgumentOutOfRangeException aus, wenn der Lastschriftbetrag kleiner als 0 ist.

  • Wenn der Lastschriftbetrag gültig ist, subtrahiert die Methode den Lastschriftbetrag vom Kontostand.

Tipp

Sie können die Standardmethode TestMethod1 löschen, da Sie sie in diesem Artikel nicht verwenden.

So erstellen Sie eine Testmethode

Der erste Test überprüft, ob ein gültiger Betrag (d. h. ein Betrag, der kleiner als der Kontostand und größer als Null ist) den richtigen Betrag aus dem Konto zurückzieht. Fügen Sie der klasse BankAccountTests die folgende Methode hinzu:

[TestMethod]
public void Debit_WithValidAmount_UpdatesBalance()
{
    // Arrange
    double beginningBalance = 11.99;
    double debitAmount = 4.55;
    double expected = 7.44;
    BankAccount account = new BankAccount("Mr. Bryan Walton", beginningBalance);

    // Act
    account.Debit(debitAmount);

    // Assert
    double actual = account.Balance;
    Assert.AreEqual(expected, actual, 0.001, "Account not debited correctly");
}

Die Methode ist einfach: Sie richtet ein neues BankAccount Objekt mit einem Anfangssaldo ein und zieht dann einen gültigen Betrag zurück. Es verwendet die Assert.AreEqual-Methode, um zu überprüfen, ob der Endsaldo wie erwartet ist. Methoden wie Assert.AreEqual, Assert.IsTrueund andere werden häufig bei Komponententests verwendet. Weitere konzeptionelle Informationen zum Schreiben eines Komponententests finden Sie unter Schreiben Ihrer Tests.

Testmethodenanforderungen

Eine Testmethode muss die folgenden Anforderungen erfüllen:

  • Es ist mit dem [TestMethod] Attribut versehen.

  • Daraufhin wird void zurückgegeben.

  • Es kann keine Parameter enthalten.

Erstellen und Ausführen des Tests

  1. Wählen Sie im Menü Erstellen die Option Projektmappe erstellen aus, oder drücken Sie STRG + UMSCHALT + B.

  2. Wenn Test-Explorer nicht geöffnet ist, öffnen Sie ihn, indem Sie Test>Test-Explorer (oder Test>Windows>Test-Explorer) in der oberen Menüleiste wählen (oder drücken Sie STRG + E, T).

  3. Wählen Sie Alle ausführen aus, oder drücken Sie STRG + R, V, um den Test auszuführen.

    Während der Test ausgeführt wird, wird die Statusleiste oben im Test-Explorer Fenster animiert. Am Ende des Testlaufs wird der Balken grün, wenn alle Testmethoden bestehen, oder rot, wenn einer der Tests fehlschlägt.

    In diesem Fall schlägt der Test fehl.

  4. Wählen Sie die Methode in Test-Explorer aus, um die Details unten im Fenster anzuzeigen.

Beheben des Codes und erneutes Ausführen der Tests

Das Testergebnis enthält eine Meldung, die den Fehler beschreibt. Möglicherweise müssen Sie einen Drilldown ausführen, um diese Meldung anzeigen zu können. Für die AreEqual-Methode zeigt die Meldung an, was erwartet wurde und was tatsächlich empfangen wurde. Erwartet haben Sie, dass der Kontostand sinkt, aber stattdessen ist er um den Betrag der Auszahlung erhöht.

Beim Komponententest wurde ein Fehler festgestellt: Der Abbuchungsbetrag wird dem Kontoguthaben hinzugerechnet, anstatt davon abgezogen zu werden.

Korrigieren des Fehlers

Um den Fehler zu beheben, ersetzen Sie in der datei BankAccount.cs die Zeile:

m_balance += amount;

Durch:

m_balance -= amount;

Erneutes Ausführen des Tests

Wählen Sie im Test-Explorer die Option Alle ausführen aus, oder drücken Sie STRG + R, V, um den Test erneut auszuführen. Der rote/grüne Balken wird grün, um anzugeben, dass der Test bestanden wurde.

Test-Explorer in Visual Studio 2019, der erfolgreiche Tests anzeigt

Test-Explorer in Visual Studio 2019, der erfolgreiche Tests anzeigt

Verwenden von Komponententests zur Verbesserung des Codes

In diesem Abschnitt wird beschrieben, wie Ein iterativer Prozess der Analyse, komponententestentwicklung und -umgestaltung Ihnen helfen kann, Ihren Produktionscode robuster und effektiver zu gestalten.

Analysieren der Probleme

Sie haben eine Testmethode erstellt, um zu bestätigen, dass ein gültiger Betrag in der Debit Methode korrekt abgezogen wird. Überprüfen Sie nun, ob die Methode eine ArgumentOutOfRangeException auslöst, wenn der Debitbetrag einer der folgenden Ist:

  • entweder höher als das Guthaben ist oder
  • unter 0 liegt.

Erstellen und Ausführen neuer Testmethoden

Erstellen Sie eine Testmethode, um das richtige Verhalten zu überprüfen, wenn der Lastschriftbetrag kleiner als 0 ist:

[TestMethod]
public void Debit_WhenAmountIsLessThanZero_ShouldThrowArgumentOutOfRange()
{
    // Arrange
    double beginningBalance = 11.99;
    double debitAmount = -100.00;
    BankAccount account = new BankAccount("Mr. Bryan Walton", beginningBalance);

    // Act and assert
    Assert.ThrowsException<System.ArgumentOutOfRangeException>(() => account.Debit(debitAmount));
}

Verwenden Sie die ThrowsException-Methode, um zu bestätigen, dass die richtige Ausnahme ausgelöst wurde. Diese Methode führt dazu, dass der Test fehlschlägt, es sei denn, ein ArgumentOutOfRangeException wird ausgelöst. Wenn Sie die im Test ausgeführte Methode vorübergehend so ändern, dass eine allgemeinere ApplicationException ausgelöst wird, wenn der Lastschriftbetrag kleiner als 0 ist, verhält sich der Test ordnungsgemäß – d. h., er schlägt fehl.

Führen Sie die folgenden Schritte aus, um den Fall zu testen, wenn der Auszahlungsbetrag größer als der Saldo ist:

  1. Erstellen Sie eine neue Testmethode mit dem Namen Debit_WhenAmountIsMoreThanBalance_ShouldThrowArgumentOutOfRange.

  2. Kopieren Sie den Methodentext aus Debit_WhenAmountIsLessThanZero_ShouldThrowArgumentOutOfRange in die neue Methode.

  3. Legen Sie die debitAmount auf eine Zahl fest, die größer als der Saldo ist.

Führen Sie die beiden Tests aus, und überprüfen Sie, ob sie bestehen.

Fortsetzen der Analyse

Die getestete Methode kann weiter verbessert werden. Mit der aktuellen Implementierung haben wir keine Möglichkeit zu wissen, welche Bedingung (amount > m_balance oder amount < 0) zu der Ausnahme führte, die während des Tests ausgelöst wird. Sie wissen nur, dass irgendwo in der Methode eine ArgumentOutOfRangeException ausgelöst wurde. Es wäre besser, wenn wir feststellen könnten, welche Bedingung in BankAccount.Debit verursachte, dass die Ausnahme ausgelöst wurde (amount > m_balance oder amount < 0), damit wir sicher sein können, dass unsere Methode die Argumente korrekt überprüft.

Sehen Sie sich die getestete Methode (BankAccount.Debit) erneut an, und beachten Sie, dass beide Bedingungsanweisungen einen ArgumentOutOfRangeException-Konstruktor verwenden, der nur den Namen des Arguments als Parameter verwendet:

throw new ArgumentOutOfRangeException("amount");

Es gibt einen Konstruktor, den Sie verwenden können, um umfassendere Informationen zu berichten: ArgumentOutOfRangeException(String, Object, String) enthält den Namen des Arguments, den Argumentwert und eine benutzerdefinierte Nachricht. Sie können die zu testde Methode umgestalten, um diesen Konstruktor zu verwenden. Sie können sogar öffentlich verfügbare Typmember verwenden, um die Fehler anzugeben.

Refaktorisiere den zu testenden Code

Definieren Sie zunächst zwei Konstanten für die Fehlermeldungen im Klassenbereich. Platzieren Sie die Definitionen in der Klasse unter Test, BankAccount:

public const string DebitAmountExceedsBalanceMessage = "Debit amount exceeds balance";
public const string DebitAmountLessThanZeroMessage = "Debit amount is less than zero";

Ändern Sie dann die beiden bedingten Anweisungen in der Debit-Methode:

if (amount > m_balance)
{
    throw new System.ArgumentOutOfRangeException("amount", amount, DebitAmountExceedsBalanceMessage);
}

if (amount < 0)
{
    throw new System.ArgumentOutOfRangeException("amount", amount, DebitAmountLessThanZeroMessage);
}

Umgestalten der Testmethoden

Umgestalten Sie die Testmethoden, indem Sie den Aufruf von Assert.ThrowsExceptionentfernen. Umschließen Sie den Aufruf von Debit() in einem try/catch-Block, fangen Sie die spezifische erwartete Ausnahme ab, und verifizieren Sie die zugehörige Meldung. Die Microsoft.VisualStudio.TestTools.UnitTesting.StringAssert.Contains-Methode bietet die Möglichkeit, zwei Zeichenfolgen zu vergleichen.

Nun könnte die Debit_WhenAmountIsMoreThanBalance_ShouldThrowArgumentOutOfRange wie folgt aussehen:

[TestMethod]
public void Debit_WhenAmountIsMoreThanBalance_ShouldThrowArgumentOutOfRange()
{
    // Arrange
    double beginningBalance = 11.99;
    double debitAmount = 20.0;
    BankAccount account = new BankAccount("Mr. Bryan Walton", beginningBalance);

    // Act
    try
    {
        account.Debit(debitAmount);
    }
    catch (System.ArgumentOutOfRangeException e)
    {
        // Assert
        StringAssert.Contains(e.Message, BankAccount.DebitAmountExceedsBalanceMessage);
    }
}

Neu testen, neu schreiben und neu ananalysieren

Derzeit behandelt die Testmethode nicht alle Fälle, die sie sollte. Wenn die zu testende Methode, die Debit Methode, einen ArgumentOutOfRangeException nicht ausgelöst hat, wenn der debitAmount größer als der Saldo (oder kleiner als Null) war, würde die Testmethode als bestanden gelten. Dieses Szenario ist nicht gut, da die Testmethode fehlschlagen soll, wenn keine Ausnahme ausgelöst wird.

Dieses Ergebnis ist ein Fehler in der Testmethode. Um das Problem zu beheben, fügen Sie eine Assert.Fail-Assertion am Ende der Testmethode hinzu, um den Fall abzudecken, in dem keine Ausnahme ausgelöst wird.

Ein erneuter Test zeigt, dass der Test jetzt fehlschlägt, wenn die richtige Ausnahme erfasst wird. Der catch-Block fängt die Ausnahme ab, aber die Methode wird weiterhin ausgeführt und schlägt bei der neuen Assert.Fail Assertion fehl. Um dieses Problem zu beheben, fügen Sie eine return-Anweisung nach dem StringAssert im catch Block hinzu. Durch erneutes Ausführen des Tests wird bestätigt, dass Sie dieses Problem behoben haben. Die endgültige Version der Debit_WhenAmountIsMoreThanBalance_ShouldThrowArgumentOutOfRange sieht wie folgt aus:

[TestMethod]
public void Debit_WhenAmountIsMoreThanBalance_ShouldThrowArgumentOutOfRange()
{
    // Arrange
    double beginningBalance = 11.99;
    double debitAmount = 20.0;
    BankAccount account = new BankAccount("Mr. Bryan Walton", beginningBalance);

    // Act
    try
    {
        account.Debit(debitAmount);
    }
    catch (System.ArgumentOutOfRangeException e)
    {
        // Assert
        StringAssert.Contains(e.Message, BankAccount.DebitAmountExceedsBalanceMessage);
        return;
    }

    Assert.Fail("The expected exception was not thrown.");
}

Schlussfolgerung

Die Verbesserungen am Testcode führten zu robusteren und informativeren Testmethoden. Aber wichtiger ist, dass sie auch den testierten Code verbessert haben.

Tipp

In diesem Artikel wird das Microsoft-Komponententestframework für verwalteten Code verwendet. Der Test-Explorer kann außerdem Tests von Komponententestframeworks von Drittanbietern ausführen, die über Adapter für den Test-Explorer verfügen. Weitere Informationen finden Sie unter Installieren von Komponententestframeworks von Drittanbietern.

Informationen zum Ausführen von Tests über eine Befehlszeile finden Sie unter VSTest.Console.exe Befehlszeilenoptionen.