Schreiben von neuem Code für eine User Story

Sind Sie ein neuer Benutzer von Visual Studio Application Lifecycle Management (ALM) und Team Foundation Server (TFS)? Fragen Sie sich, wie Sie und Ihr Team die aktuelle Version dieser Tools optimal zur Erstellung einer App nutzen können?

Dann nehmen Sie sich einige Minuten Zeit, um schrittweise die beiden Kapitel des vorliegenden Tutoriums durchzuarbeiten. Begleiten Sie einen Tag lang die beiden Entwickler Peter und Julia bei Fabrikam Fiber, einem fiktiven Unternehmen, das Kabelfernsehen und verwandte Dienste anbietet. Sie finden Beispiele dafür, wie Sie Visual Studio und TFS zum Auschecken und Aktualisieren von Code, zum Anhalten der Arbeit bei Unterbrechungen, zum Anfordern einer Codeüberprüfung, zum Einchecken der Änderungen und zum Durchführen weiterer Aufgaben verwenden können.

Was bisher geschah

Das Team hat vor kurzem Visual Studio und Team Foundation Server für die Anwendungslebenszyklus-Verwaltung (ALM) eingeführt. Es hat seine Server und Clientcomputer installiert, ein Backlog erstellt, eine Iteration geplant und andere Planungsarbeiten zur Vorbereitung der App-Entwicklung durchgeführt.

Übersicht über dieses Kapitel

Peter wiederholt kurz sein Backlog und wählt die Aufgabe aus, die er heute bearbeiten wird. Er schreibt Komponententests für den Code, den er entwickeln möchte. In der Regel führt er die Tests mehrmals pro Stunde durch, schreibt dann nach und nach detailliertere Tests und anschließend den Code für den erfolgreichen Abschluss der Tests. Er bespricht die Schnittstelle des Codes regelmäßig mit den Kollegen, die die von ihm geschriebene Methode verwenden werden.

Hinweis

Die Funktionen "Meine Arbeit" und "Codeabdeckung", die in diesem Thema behandelt werden, sind nur in Visual Studio Premium und Visual Studio Ultimate verfügbar.

In diesem Thema

  • Persönliches Backlog überprüfen und die Aufgaben zum Starten der Arbeit vorbereiten

  • Den ersten Komponententest erstellen

  • Einen Stub für den neuen Code erstellen

  • Den ersten Test ausführen

  • Einig werden über die API

  • Rot, Grün, Umgestalten...

  • Codeabdeckung

  • Wann sind wir fertig?

  • Die Änderungen einchecken

Persönliches Backlog überprüfen und die Aufgaben zum Starten der Arbeit vorbereiten

In Team Explorer öffnet Peter die Seite Meine Arbeit. Das Team hat sich darauf geeinigt, dass Peter während des aktuellen Sprints an dem Element "Rechnungsstatus auswerten" arbeitet, das die höchste Priorität im Product Backlog hat. Peter entscheidet, mit "Mathematische Funktionen implementieren" zu beginnen, einer dem Element mit der höchsten Priorität im Product Backlog untergeordneten Aufgabe. Er zieht diese Aufgabe aus der Liste Verfügbare Arbeitsaufgaben in die Liste Arbeitsaufgaben in Bearbeitung & Änderungen.

Überprüfen des persönlichen Backlogs und Vorbereiten der Aufgaben zum Starten der Arbeit

Aufgabenplanungsliste auf der Seite „Meine Arbeit“ in Team Navigator

  1. In Team Explorer:

    1. Wenn Sie nicht bereits über eine Verbindung mit dem Teamprojekt verfügen, in dem Sie arbeiten möchten, stellen Sie eine Verbindung mit dem Teamprojekt her.

    2. Wählen Sie Symbol "Startseite" Startseite und dann die Option Symbol „Meine Arbeit“ Meine Arbeit aus.

  2. Ziehen Sie auf der Seite Meine Arbeit die Aufgabe aus der Liste Verfügbare Arbeitsaufgaben in den Abschnitt Arbeitsaufgaben in Bearbeitung.

    Sie können auch eine Aufgabe in der Liste Verfügbare Arbeitsaufgaben auswählen und dann auf Start klicken.

Inkrementeller Entwurfsarbeitsplan

Bei der Entwicklung von Code geht Peter in der Regel schrittweise vor. Normalerweise dauert jeder Schritt zwischen 10 Minuten und einer Stunde. In jedem Schritt schreibt er einen neuen Komponententest und ändert den entwickelten Code so, dass zusätzlich zu den bereits geschriebenen Tests auch der neue Test bestanden wird. Manchmal schreibt er den neuen Test, bevor er den Code ändert, und manchmal er ändert den Code, bevor er den Test schreibt. Manchmal gestaltet er Code um. Das bedeutet, dass er lediglich den Code optimiert, ohne neue Tests hinzuzufügen. Einen bestandenen Test ändert er nur dann, wenn er der Meinung ist, dass eine Anforderung nicht korrekt dargestellt wurde.

Am Ende jedes kleinen Schritts führt er alle Komponententests aus, die für den jeweiligen Codebereich relevant sind. Der Schritt wird erst dann als vollständig betrachtet, wenn jeder Test erfolgreich abgeschlossen wurde.

Er überprüft den Code erst nach Abschluss der gesamten Aufgabe in Team Foundation Server.

Peter verfasst für diese aus kleinen Schritten bestehende Folge einen groben Plan. Er weiß, dass sich die Details und die genaue Reihenfolge von nachfolgenden Plänen mit fortschreitender Arbeit wahrscheinlich ändern werden. Im Folgenden wird seine ursprüngliche Liste für diese bestimmte Aufgabe erforderlichen Schritte dargestellt:

  1. Testmethodenstub erstellen, d. h. nur die Signatur der Methode.

  2. Einen typischen Fall erfüllen.

  3. Einen großen Bereich testen. Sicherstellen, dass der Code ordnungsgemäß auf einen großen Wertebereich reagiert.

  4. Bei negativem Ergebnis Ausnahme ausgeben. Falsche Parameter ordnungsgemäß behandeln.

  5. Codeabdeckung. Stellen Sie sicher, dass mindestens 80% des Codes durch die Komponententests ausgeführt werden.

Einige Kollegen fügen einen solchen Plan als Kommentare in ihren Code ein. Andere merken sich den Plan lediglich. Peter bevorzugt es, die Liste der Schritte in das Feld "Beschreibung" der Arbeitsaufgabe zu schreiben. Sollte er sich dann vorübergehend einer dringenderen Aufgabe widmen müssen, weiß er später genau, wo die Liste zu finden ist.

Den ersten Komponententest erstellen

Peter beginnt mit der Erstellung eines Komponententests. Das tut er deshalb, weil er ein Codebeispiel schreiben möchte, das die neue Klasse verwendet.

Da dies der erste Komponententest für die zu testende Klassenbibliothek ist, erstellt er ein neues Komponententestprojekt. Er öffnet das Dialogfeld Neues Projekt und wählt die Optionen Visual C#, Test und anschließend Komponententestprojekt aus.

Im Dialogfeld "Neues Projekt" ausgewählter Komponententest

Das Komponententestprojekt stellt eine C#-Datei bereit, in der er sein Beispiel schreiben kann. In diesem Stadium möchte er nur veranschaulichen, wie eine der neuen Methoden aufgerufen wird:

using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace Fabrikam.Math.UnitTest
{
    [TestClass]
    public class UnitTest1
    {
        [TestMethod]
        // Demonstrates how to call the method.
        public void SignatureTest()
        {
            // Create an instance:
            var math = new Fabrikam.Math.LocalMath();

            // Get a value to calculate:
            double input = 0.0;

            // Call the method:
            double actualResult = math.SquareRoot(input);

            // Use the result:
            Assert.AreEqual(0.0, actualResult);
        }
    }
}

Er schreibt das Beispiel in eine Testmethode, da es funktionieren soll, wenn er den Code fertig gestellt hat.

Erstellen eines Komponententestprojekts und von Methoden

Normalerweise wird für jedes zu testende Projekt ein neues Testprojekt erstellt. Wenn aber bereits ein Testprojekt vorhanden ist, können Sie diesem neue Testmethoden und Klassen hinzufügen.

Für dieses Verfahren wird das Visual Studio-Komponententestframework verwendet. Sie können aber auch Frameworks anderer Anbieter verwenden. Test-Explorer funktioniert ebenso mit anderen Frameworks, sofern Sie den entsprechenden Adapter installieren.

  • Erstellen Sie gegebenenfalls ein Testprojekt.

    • Wählen Sie im Dialogfeld Neues Projekt eine Sprache aus, z. B. Visual Basic, Visual C++ oder Visual C#. Wählen Sie Test und dann Komponententestprojekt aus.
  • Fügen Sie die Tests zur bereitgestellten Testklasse hinzu. Jeder Komponententest ist eine Methode.

    Jedem Komponententest muss das TestMethod-Attribut vorangestellt werden. Die Komponententestmethode darf keine Parameter aufweisen. Sie können für eine Komponententestmethode einen beliebigen Namen verwenden:

            [TestMethod]
            public void SignatureTest()
            {...}
    
        <TestMethod()>
        Public Sub SignatureTest()
        ...
        End Sub
    
  • Jede Testmethode muss eine Methode der Assert-Klasse aufrufen und angeben, ob sie erfolgreich oder fehlerhaft war. In der Regel überprüfen Sie, ob die erwarteten und tatsächlichen Ergebnisse einer Operation übereinstimmen:

    Assert.AreEqual(expectedResult, actualResult);
    
    Assert.AreEqual(expectedResult, actualResult)
    
  • Testmethoden können andere gewöhnliche Methoden aufrufen, die nicht das TestMethod-Attribut aufweisen.

  • Sie können die Tests in mehreren Klassen organisieren. Jeder Klasse muss das TestClass-Attribut vorangestellt werden.

    [TestClass]
    public class UnitTest1
    { ... }
    
    <TestClass()>
    Public Class UnitTest1
    ...
    End Class
    

Weitere Informationen zum Schreiben von Komponententests in C++ finden Sie unter Schreiben von Komponententests für C/C++ mit dem Microsoft-Komponententestframework für C++.

Einen Stub für den neuen Code erstellen

Als Nächstes erstellt Peter ein Klassenbibliotheksprojekt für den neuen Code. Es gibt nun ein Projekt für den Code in der Entwicklung und ein Projekt für die Komponententests. Er fügt einen Projektverweis vom Testprojekt zum Code in der Entwicklung hinzu.

Projektmappen-Explorer mit Test- und Klassenprojekten

In dem neuen Projekt fügt er die neue Klasse und eine Mindestversion der Methode hinzu, mit der sich der Test zumindest erfolgreich erstellen lässt. Am schnellsten lässt sich dies durch Generieren eines Klassen- und Methodenstubs über den Aufruf im Test erreichen.

        public double SquareRoot(double p)
        {
            throw new NotImplementedException();
        }

Generieren von Klassen und Methoden aus Tests

Erstellen Sie zunächst das Projekt, dem Sie die neue Klasse hinzufügen möchten, sofern es noch nicht vorhanden ist.

Generieren einer Klasse

  1. Platzieren Sie den Cursor in einem Beispiel der zu generierenden Klasse, zum Beispiel LocalMath. Klicken Sie im Kontextmenü auf Code generieren und Neuer Typ.

  2. Legen Sie im Dialogfeld Neuer Typ unter Projekt das Klassenbibliotheksprojekt fest. Im vorliegenden Beispiel handelt es sich hierbei um Fabrikam.Math.

Generieren einer Methode

  • Platzieren Sie den Cursor in einem Aufruf der Methode, zum Beispiel SquareRoot. Klicken Sie im Kontextmenü auf Code generieren und Methodenstub.

Den ersten Test ausführen

Peter erstellt den Test und führt ihn aus, indem er die Tastenkombination "STRG+R, T" drückt. Im Testergebnis wird ein roter Fehlerindikator angezeigt. Der Test erscheint in der Liste Tests mit Fehlern.

Komponententest-Explorer zeigt einen fehlerhaften Test an

Er nimmt eine einfache Änderungen am Code vor:

       public double SquareRoot(double p)
        {
            return 0.0;
        }

Er führt den Test erneut aus und übergibt ihn:

Komponententest-Explorer mit einem bestandenen Test

Ausführen von Tests

Test-Explorer zeigt die Schaltfläche "Alles ausführen" an

  • Klicken Sie im Menü Test auf Ausführen und Alle Tests.

    – oder –

  • Wenn der Test-Explorer geöffnet ist, wählen Sie die Option Alle ausführen aus.

    - oder -

  • Platzieren Sie den Cursor in einer Testcodedatei und drücken Sie STRG+R, T.

  • Wenn ein Test unter Tests mit Fehlern angezeigt wird, gehen Sie folgendermaßen vor:

    Öffnen Sie den Test, indem Sie z. B. auf den Namen doppelklicken.

    Daraufhin wird die Stelle angezeigt, an der der Test fehlerhaft verlaufen ist ist.

Wenn Sie eine vollständige Liste der Tests anzeigen möchten, klicken Sie auf Alle anzeigen. Wenn Sie zur Zusammenfassung zurückzukehren möchten, wählen Sie die Ansicht Startseite aus.

Wenn Sie die Details eines Testergebnisses anzeigen möchten, wählen Sie den Test im Test-Explorer aus.

Wenn Sie zum Testcode navigieren möchten, doppelklicken Sie in Test-Explorer auf den Test, oder wählen Sie im Kontextmenü die Option Test öffnen aus.

Wenn Sie einen Test debuggen möchten, öffnen Sie das Kontextmenü für einen oder mehrere Tests, und wählen Sie dann die Option Ausgewählte Tests debuggen aus.

Wenn Sie bei jeder Erstellung der Projektmappe Tests im Hintergrund ausführen möchten, schalten Sie die Option Nach dem Buildvorgang Tests ausführen ein oder aus. Zuvor fehlerhafte Tests werden zuerst ausgeführt.

Einig werden über die Schnittstelle

Peter wendet sich über Lync an seine Kollegin Julia und gibt seinen Bildschirm für sie frei. Sie wird seine Komponente später verwenden. Er zeigt ihr sein erstes Beispiel.

Julia befindet das Beispiel für gut, merkt jedoch an, dass viele Funktionen diesen Test erfolgreich bestehen würden.

Peter gibt zurück, dass mit diesem ersten Test lediglich die Korrektheit des Namens und der Paramater der Funktion überprüft werden soll. Anschließend kann dann Test geschrieben werden, der die Hauptanforderung dieser Funktion erfasst.

Zusammen schreiben sie den folgenden Test:

  
      [TestMethod]
        public void QuickNonZero()
        {
            // Create an instance to test:
            LocalMath math = new LocalMath();

            // Create a test input and expected value:
            var expectedResult = 4.0;
            var inputValue = expectedResult * expectedResult;

            // Run the method:
            var actualResult = math.SquareRoot(inputValue);

            // Validate the result:
            var allowableError = expectedResult/1e6;
            Assert.AreEqual(expectedResult, actualResult, allowableError,
                "{0} is not within {1} of {2}", actualResult, allowableError, expectedResult);
        }

Tipp

Für diese Funktion verwendet Peter die Test-First-Entwicklung. Zunächst schreibt er den Komponententest einer Funktion und anschließend den Code, der den Test bestehen lässt.Diese Vorgehensweise hält er aber nicht immer für praktikabel. Daher schreibt er die Tests manchmal erst im Anschluss an den Code.Das Schreiben von Komponententests an sich – sei es vor oder nach dem Code – hält er aber für sehr wichtig, weil dadurch der Code stabil bleibt.

Rot, Grün, Umgestalten...

Peter geht nach einem bestimmten Zyklus vor, in dem er wiederholt einen Test schreibt und bestätigt, dass er fehlerhaft verläuft. Daraufhin schreibt er einen Code, der den Test erfolgreich abschließen lässt und erwägt eine Umgestaltung, d. h. er erweitert den Code, ohne die Tests zu ändern.

Rot

Peter drückt die Tastenkombination "STRG+R, T", um den neuen Test auszuführen, den er mit Julia erstellt hat. Wenn er einen Test geschrieben hat, führt er ihn immer aus, um sicherzustellen, dass ein Fehler auftritt. Erst dann schreibt er den Code, der den Test erfolgreich abschließen lässt. An diese Vorgehensweise hält er sich, seit er einmal vergessen hat, einige seiner geschriebenen Tests mit Assertionen zu versehen. Das fehlerhafte Ergebnis verschafft ihm die Gewissheit, dass das Testergebnis die Erfüllung einer Anforderung ordnungsgemäß wiedergeben wird, sobald er den Code schreibt, der den Test erfolgreich abschließen lässt.

Des Weiteren empfiehlt es sich, die Option Nach dem Buildvorgang Tests ausführen zu aktivieren. Damit werden die Tests bei jeder Erstellung der Projektmappe im Hintergrund ausgeführt, und Sie erhalten einen fortlaufenden Bericht über den Teststatus des Codes. Anfangs war Peter etwas skeptisch, weil er eine Beeinträchtigung der Reaktionsfähigkeit von Visual Studio befürchtete. Diese Sorge erwies sich allerdings als weitgehend unbegründet.

Komponententest-Explorer mit einem fehlerhaften Test

Grün

Peter unternimmt einen ersten Versuch, den Code für seine Methode zu schreiben:

    public class LocalMath
    {
        public double SquareRoot(double x)
        {
            double estimate = x;
            double previousEstimate = -x;
            while (System.Math.Abs(estimate - previousEstimate) > estimate / 1000)
            {
                previousEstimate = estimate;
                estimate = (estimate * estimate - x) / (2 * estimate);
            }
            return estimate;
        }
        

Peter führt die Tests erneut aus. Alle Tests werden bestanden:

Komponententest-Explorer mit zwei bestandenen Tests

Umgestalten

Da der Code nun seine Hauptfunktion erfüllt, sucht Peter nach Möglichkeiten, ihn zu optimieren bzw. ihn in Zukunft leichter ändern zu können. Er stellt fest, dass er die Anzahl von Berechnungen reduzieren kann, die in der Schleife ausgeführt werden:

public class LocalMath
    {
        public double SquareRoot(double x)
        {
            double estimate = x;
            double previousEstimate = -x;
            while (System.Math.Abs(estimate - previousEstimate) > estimate / 1000)
            {
                previousEstimate = estimate; 
                estimate = (estimate + x / estimate) / 2;
                //was: estimate = (estimate * estimate - x) / (2 * estimate);
            }
            return estimate;
        }

Er überprüft, ob die Tests trotzdem bestanden werden:

Komponententest-Explorer mit zwei bestandenen Tests

Tipp

Jede Änderung, die Sie bei der Codeentwicklung vornehmen, sollte entweder eine Umgestaltung oder eine Erweiterung sein:

  • Eine Umgestaltung bedeutet, dass Sie die Tests nicht ändern, da keine neuen Funktionen hinzugefügt werden.

  • Eine Erweiterung bedeutet, dass Tests hinzugefügt und Codeänderungen vorgenommen werden, die für das Bestehen von vorhandenen und neuen Tests erforderlich sind.

Wenn Sie vorhandenen Code an geänderte Anforderungen anpassen, löschen Sie gleichzeitig alte Tests, die den aktuellen Anforderungen nicht mehr entsprechen.

Vermeiden Sie es, Tests zu ändern, die bereits bestanden wurden.Fügen Sie stattdessen lieber neue Tests hinzu.Schreiben Sie nur Tests, die einer echten Anforderung entsprechen.

Führen Sie die Tests nach jeder Änderung durch.

...und noch einmal

Peter setzt die Reihe von Erweiterungs- und Umgestaltungsschritten fort. Seine Liste dient ihm dabei als grober Leitfaden. D. h. es folgt nicht auf jede Erweiterung ein Umgestaltungsschritt, und manchmal werden auch mehrere Umgestaltungsschritte hintereinander ausgeführt. Allerdings folgen auf jede Codeänderung Komponententests.

Manchmal fügt er einen Test hinzu, der keine Codeänderung erfordert. Dieser Test macht ihn noch sicherer, dass sein Code ordnungsgemäß funktioniert. Er möchte beispielsweise überprüfen, ob die Funktion einen breites Eingabespektrum abdeckt. Hierzu schreibt er weitere Tests, z. B.:

        [TestMethod]
        public void SqRtValueRange()
        {
            LocalMath math = new LocalMath();
            for (double expectedResult = 1e-8;
                expectedResult < 1e+8;
                expectedResult = expectedResult * 3.2)
            {
                VerifyOneRootValue(math, expectedResult);
            }
        }
        private void VerifyOneRootValue(LocalMath math, double expectedResult)
        {
            double input = expectedResult * expectedResult;
            double actualResult = math.SquareRoot(input);
            Assert.AreEqual(expectedResult, actualResult, expectedResult / 1e6);
        }

Dieser Test ist bei seiner ersten Ausführung erfolgreich:

Komponententest-Explorer mit drei bestandenen Tests

Um sich zu vergewissern, dass dies kein falsch-positives Ergebnis ist, baut er vorübergehend einen kleinen Fehler in den Test ein, der den Test fehlerhaft verlaufen lässt. Nachdem der sich den Fehler angesehen hat, behebt er ihn wieder.

Tipp

Es empfiehlt sich, einen Test immer zunächst fehlschlagen zu lassen, bevor er erfolgreich abgeschlossen wird.

Ausnahmen

Peter wendet sich nun dem Schreiben von Tests für Ausnahmeeingaben zu:

[TestMethod]
        public void RootTestNegativeInput()
        {
            LocalMath math = new LocalMath();
            try
            {
                math.SquareRoot(-10.0);
            }
            catch (ArgumentOutOfRangeException)
            {
                return;
            }
            catch
            {
                Assert.Fail("Wrong exception on negative input");
                return;
            }
            Assert.Fail("No exception on negative input");
        }

Bei diesem Test wird der Code in eine Schleife gesetzt. Er muss die Schaltfläche Abbrechen in Test-Explorer betätigen. Dadurch wird der Code innerhalb von 10 Sekunden angehalten.

Peter möchte überprüfen, ob eine Endlosschleife nicht auch auf dem Buildserver auftreten kann. Der Server erzwingt zwar bei einer vollständigen Ausführung ein Timeout, dieses ist aber sehr lang und würde zu einer beträchtlichen Verzögerung führen. Daher fügt er diesem Test ein explizites Timeout hinzu:

        [TestMethod, Timeout(1000)]
        public void RootTestNegativeInput()
        {...

Das explizite Timeout bewirkt, dass der Test fehlschlägt.

Peter aktualisiert dann den Code, um diesen Ausnahmefall zu behandeln:

       public double SquareRoot(double x)
        {
            if (x <= 0.0) 
            {
                throw new ArgumentOutOfRangeException();
            }

Regression

Der neue Test wird bestanden, es tritt allerdings eine Regression auf. Der eben noch erfolgreiche Test schlägt nun fehl:

Zuvor bestandener Komponententest ist fehlerhaft

Peter sucht den Fehler und behebt ihn:

      public double SquareRoot(double x)
        {
            if (x < 0.0)  // not <=
            {
                throw new ArgumentOutOfRangeException();
            }

Anschließend sind alle Tests erfolgreich:

Komponententest-Explorer mit vier bestandenen Tests

Tipp

Vergewissern Sie sich nach jeder Codeänderung, dass alle Tests bestanden werden.

Codeabdeckung

In gewissen Abständen während seiner Arbeit sowie vor dem Einchecken des Codes ruft Peter den Bericht "Codeabdeckung" ab. In diesem wird dargestellt, welcher Anteil des Codes durch die Tests untersucht wurde.

Peters Team strebt einen Anteil von mindestens 80% an. Für generierten Code wird diese Anforderung weniger streng gehandhabt, da es schwierig sein kann, für diesen Codetyp eine hohe Abdeckung zu erreichen.

Eine gute Codeabdeckung garantiert weder die vollständige Funktionalität einer getesteten Komponente noch die Funktionsfähigkeit des Codes in jedem Bereich von Eingabewerten. Trotzdem gibt es einen engen Zusammenhang zwischen der Abdeckung von Codezeilen und der des verhaltensgesteuerten Bereichs einer Komponente. Daher bestärkt eine gute Codeabdeckung ein Team darin, dass sie auch wirklich den erforderlichen Großteil des Codeverhaltens testen.

Um den Bericht "Codeabdeckung" abzurufen, wählen Sie im Menü Tests die Optionen Ausführen und Codeabdeckung für alle Tests analysieren aus. Führen Sie anschließend alle Tests erneut aus.

Codeabdeckungsergebnis und Schaltfläche "Farbe anzeigen"

Peter erhält eine Gesamtabdeckung von 86%. Wenn er die Summe im Bericht erweitert, sieht er, dass der Code, den er selbst entwickelt, eine Abdeckung von 100% aufweist. Das ist äußerst zufriedenstellend, da der zu testende Code am wichtigsten ist. Die nicht abgedeckten Abschnitte befinden sich nämlich in den Tests selbst. Durch Betätigen der Umschaltfläche Codeabdeckungsfärbung anzeigen kann Peter herausfinden, welche Teile des Testcodes nicht untersucht wurden. Er beschließt allerdings, dass diese Abschnitte für die Codeabdeckung bedeutungslos sind, da sie sich im Testcode befinden und nur bei der Feststellung eines Fehlers verwendet werden.

Wenn Sie überprüfen möchten, ob ein bestimmter Test in bestimmte Codeverzweigungen hineinreicht, können Sie die Option Codeabdeckungsfärbung anzeigen aktivieren und anschließend den Test über den Befehl Ausführen im Kontextmenü ausführen.

Wann sind wir fertig?

Peter fährt fort, den Code in kleinen Schritten zu aktualisieren, bis die folgenden Kriterien erfüllt sind:

  • Alle verfügbaren Komponententests wurden bestanden.

    Bei Projekten mit besonders vielen Komponententests können Entwickler möglicherweise nicht abwarten, bis alle Tests ausgeführt wurden. Stattdessen führt das Projekt einen abgegrenzten Eincheckvorgang aus, bei dem alle automatisierten Tests für jedes eingecheckte Shelveset ausgeführt und anschließend in der Quellstruktur zusammengeführt werden. Das Einchecken wird abgelehnt, wenn die Ausführung fehlschlägt. So kann der Entwickler einen minimalen Satz von Komponententests auf einem eigenen Computer ausführen und anschließend andere Aufgaben fortsetzen, ohne den Build zu beschädigen. Weitere Informationen finden Sie unter Verwenden eines abgegrenzten Eincheckbuildprozesses zur Überprüfung von Änderungen.

  • Die Codeabdeckung entspricht dem Standard des Teams. Die Projektanforderung liegt in der Regel bei 75%.

  • Die Komponententests simulieren alle Aspekte des erforderlichen Verhaltens, einschließlich typischer und Ausnahmeeingaben.

  • Der Code ist leicht verständlich und erweiterbar.

Wenn alle genannten Kriterien erfüllt sind, kann Peter den Code in die Quellcodeverwaltung einchecken.

Grundlagen der Codeentwicklung mit Komponententests

Peter wendet bei der Codeentwickelung die folgenden Grundlagen an:

  • Komponententests zusammen mit dem Code entwickeln und während der Entwicklung häufig ausführen. Die Komponententests stellen die Spezifikation der Komponente dar.

  • Komponententests nur bei geänderten Anforderungen oder falschen Tests ändern. Neue Tests bei der Erweiterung der Codefunktionalität nach und nach hinzufügen.

  • Testziel: Mindestens 75% Codeabdeckung. Regelmäßig und vor dem Einchecken des Quellcodes die Codeabdeckungsergebnisse überprüfen.

  • Die Komponententests zusammen mit dem Code einchecken, sodass sie von den fortlaufenden oder regulären Serverbuildvorgängen ausgeführt werden.

  • Für jede einzelne Funktion ggf. zuerst den Komponententest schreiben. Tun Sie dies, bevor Sie den Code entwickeln, der die Funktion erfüllt.

Die Änderungen einchecken

Bevor Peter die Änderungen eincheckt, gibt er erneut über Lync seinen Bildschirm an seine Kollegin Julia frei. Auf diese Weise kann sie seine Entwicklungen informell und interaktiv überprüfen. Die Tests werden weiterhin im Fokus ihrer Diskussion stehen, da für Julia hauptsächlich der Zweck des Codes relevant ist und nicht seine Funktionsweise. Julia sagt, dass der von Peter geschriebene Code ihren Anforderungen entspricht.

Peter checkt alle vorgenommenen Änderungen ein, einschließlich der Tests und des Codes, und ordnet sie der abgeschlossenen Aufgabe zu. Beim Einchecken wird das automatisierte Buildsystem des Teams in die Warteschlange gestellt, damit seine Änderungen anhand des Buildprozesses für den CI-Build des Teams überprüft werden können. Dies trägt zur Fehlerminimierung in der Codebasis des Teams bei. Bei dem Buildprozess werden in einer unveränderten und von den Entwicklungscomputern getrennten Umgebung alle vom Team vorgenommenen Änderungen erstellt und getestet.

Peter wird benachrichtigt, sobald der Build abgeschlossen ist. Im Fenster mit den Buildergebnissen sieht er, dass der Build erfolgreich erstellt und alle Tests bestanden wurden.

Die Änderungen einchecken

Einchecken der ausstehenden Änderungen

  1. Wählen Sie in der Menüleiste die Optionen Ansicht und Team Explorer aus.

  2. Wählen Sie in Team Explorer die Option Startseite und dann Meine Arbeit aus.

  3. Wählen Sie auf der Seite Meine Arbeit die Option Einchecken aus.

  4. Überprüfen Sie den Inhalt der Seite Ausstehende Änderungen auf folgende Kriterien:

    • Alle relevanten Änderungen werden unter Eingeschlossene Änderungen aufgeführt

    • Alle relevanten Arbeitsaufgaben werden unter Verknüpfte Arbeitsaufgaben aufgeführt.

  5. Geben Sie einen Kommentar ein. So vermitteln Sie den Teammitgliedern den Zweck der vorgenommenen Änderungen, wenn sie sich den Versionskontrollverlauf der geänderten Dateien und Ordner ansehen.

  6. Wählen Sie Einchecken aus.

Fortlaufende Integration des Codes

Weitere Informationen zum Definieren eines Bildprozesses mit fortlaufender Integration finden Sie unter Einrichten eines CI-Builds. Nach der Einrichtung dieses Buildprozesses können Sie sich auf Wunsch über die Ergebnisse der Teambuilds benachrichtigen lassen.

Peter wird informiert, dass CI erstellt wurde

CI-Buildergebnisse

Weitere Informationen finden Sie unter Ausführen, Überwachen und Verwalten von Builds.

Weiter (Arbeit anhalten, Fehler reparieren und Codeüberprüfung durchführen)