Sdílet prostřednictvím


Den v životě vývojáře devops: Napište nový kód pro uživatelský příběh

Azure DevOps Services | Azure DevOps Server 2022 – Azure DevOps Server 2019

Visual Studio 2019 | Visual Studio 2022

V tomto kurzu se dozvíte, jak vy a váš tým získáte maximální výhodu z nejnovějších verzí Správa verzí Team Foundation (TFVC) a sady Visual Studio pro sestavení aplikace. Tento kurz obsahuje příklady použití sady Visual Studio a TFVC k rezervování a aktualizaci kódu, pozastavení práce při přerušení, vyžádání kontroly kódu, vrácení změn se změnami a provádění dalších úloh.

Když tým přijme sadu Visual Studio a TFVC ke správě kódu, nastaví server a klientské počítače, vytvoří backlog, naplánuje iteraci a dokončí další plánování potřebné k zahájení vývoje aplikace.

Vývojáři si prohlédnou backlogy a vyberou úkoly, na které mají pracovat. Zapisují testy jednotek pro kód, který plánují vyvíjet. Obvykle testy spouští několikrát za hodinu, postupně zapisují podrobnější testy a pak zapíšou kód, který je projde. Vývojáři často diskutují o rozhraní kódu s kolegy, kteří budou používat metodu, kterou píše.

Nástroje Pro kontrolu práce a kódu sady Visual Studio pomáhají vývojářům spravovat svou práci a spolupracovat s kolegy.

Poznámka:

Funkce Visual Studio My Work a Code Review jsou k dispozici v následujících edicích:

  • Visual Studio 2022: Visual Studio Community, Visual Studio Professional a Visual Studio Enterprise
  • Visual Studio 2019: Visual Studio Professional a Visual Studio Enterprise

Kontrola pracovních položek a příprava na zahájení práce

Tým souhlasil s tím, že během aktuálního sprintu budete pracovat na vyhodnocení stavu faktury, položky s nejvyšší prioritou v backlogu produktu. Rozhodnete se začít s implementací matematických funkcí, podřízeným úkolem položky backlogu s nejvyšší prioritou.

V Průzkumníku týmu sady Visual Studio na stránce Moje práce přetáhnete tento úkol ze seznamu Dostupné pracovní položky do seznamu Probíhající práce.

Kontrola backlogu a příprava úkolů na zahájení práce

Snímek obrazovky se stránkou Moje práce

  1. Pokud v Team Exploreru ještě nejste připojení k projektu, ve které chcete pracovat, připojte se k projektu.

  2. Na domovské stránce vyberte Moje práce.

  3. Na stránce Moje práce přetáhněte úkol ze seznamu Dostupné pracovní položky do oddílu Probíhající práce.

    Můžete také vybrat úkol v seznamu Dostupné pracovní položky a pak vybrat Spustit.

Koncept plánu přírůstkové práce

Kód vyvíjíte v řadě malých kroků. Každý krok obvykle trvá déle než hodinu a může trvat až 10 minut. V každém kroku napíšete nový test jednotek a změníte kód, který vyvíjíte, aby projde novým testem kromě testů, které jste už napsali. Někdy napíšete nový test před změnou kódu a někdy změníte kód před napsání testu. Někdy refaktorujete. To znamená, že kód jen vylepšíte, aniž byste museli přidávat nové testy. Nikdy nezměníte test, který projde, pokud se nerozhodnete, že správně nepředstavuje požadavek.

Na konci každého malého kroku spustíte všechny testy jednotek, které jsou relevantní pro tuto oblast kódu. Tento krok neberete v úvahu, dokud neproběhne každý test.

Kód na Azure DevOps Server nekontrolujete, dokud nedokončíte celou úlohu.

Pro tuto sekvenci malých kroků si můžete zapsat hrubý plán. Víte, že přesné podrobnosti a pořadí pozdějších změn se pravděpodobně změní při práci. Tady je počáteční seznam kroků pro tento konkrétní úkol:

  1. Vytvořte zástupný znak testovací metody, tj. pouze podpis metody.
  2. Uspokojte jeden konkrétní typický případ.
  3. Otestujte širokou škálu. Ujistěte se, že kód správně reaguje na velký rozsah hodnot.
  4. Výjimka záporná. Řádně zachytáte nesprávné parametry.
  5. Pokrytí kódu Ujistěte se, že testy jednotek provádí alespoň 80 % kódu.

Někteří vývojáři napíšou tento druh plánu v komentářích v testovacím kódu. Ostatní si jen zapamatují svůj plán. Může být užitečné napsat seznam kroků v poli Popis pracovní položky Úkolu. Pokud potřebujete dočasně přepnout na naléhavější úkol, víte, kde seznam najít, až se k němu budete moct vrátit.

Vytvoření prvního testu jednotek

Začněte vytvořením testu jednotek. Začněte testem jednotek, protože chcete napsat příklad kódu, který používá vaši novou třídu.

Toto je první test jednotek pro knihovnu tříd, kterou testujete, takže vytvoříte nový projekt testování jednotek.

  1. Vyberte Soubor>nový projekt.
  2. V dialogovém okně Vytvořit nový projekt vyberte šipku vedle všech jazyků a vyberte C#, vyberte šipku vedle všech typů projektů a zvolte Test a pak vyberte PROJEKT MSTest Test.
  3. Zvolte Další a pak vyberte Vytvořit.

Snímek obrazovky s vybranou možností Test jednotek v dialogovém okně Vytvořit nový projekt

V editoru kódu nahraďte obsah UnitTest1.cs následujícím kódem. V této fázi chcete jenom ilustrovat způsob vyvolání jedné z nových metod:

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);
        }
    }
}

Příklad napíšete v testovací metodě, protože v době psaní kódu chcete, aby příklad fungoval.

Vytvoření projektu a metod testování jednotek

Obvykle vytvoříte nový testovací projekt pro každý testovaný projekt. Pokud už testovací projekt existuje, můžete přidat nové testovací metody a třídy.

Tento kurz používá architekturu Visual Studio Unit Test Framework, ale můžete také použít architektury od jiných poskytovatelů. Průzkumník testů funguje stejně dobře s jinými architekturami za předpokladu, že nainstalujete příslušný adaptér.

  1. Pomocí předchozích kroků vytvořte testovací projekt. Můžete zvolit jazyky, jako jsou C#, F# a Visual Basic.

  2. Přidejte testy do zadané třídy testu. Každý test jednotek je jedna metoda.

    • Každý test jednotek musí mít předponu TestMethod atributu a metoda testu jednotek by neměla mít žádné parametry. Pro metodu testování jednotek můžete použít libovolný název:

      [TestMethod]
      public void SignatureTest()
      {...}
      
      <TestMethod()>
      Public Sub SignatureTest()
      ...
      End Sub
      
    • Každá testovací metoda by měla volat metodu Assert třídy, která označuje, jestli byla úspěšná nebo neúspěšná. Obvykle ověříte, že očekávané a skutečné výsledky operace jsou stejné:

      Assert.AreEqual(expectedResult, actualResult);
      
      Assert.AreEqual(expectedResult, actualResult)
      
    • Vaše testovací metody mohou volat jiné běžné metody, které nemají TestMethod atribut.

    • Testy můžete uspořádat do více než jedné třídy. Každá třída musí mít předponu atributu TestClass .

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

Informace o tom, jak psát testy jednotek v jazyce C++, naleznete v tématu Zápis testů jednotek pro C/C++ pomocí rozhraní Microsoft Unit Testing Framework pro C++.

Vytvoření zástupných procedur pro nový kód

Dále vytvořte projekt knihovny tříd pro nový kód. Teď je projekt pro kód ve vývoji a projekt pro testy jednotek. Přidejte odkaz na projekt z testovacího projektu do kódu v rámci vývoje.

Snímek obrazovky Průzkumník řešení s projekty testování a třídy

V novém projektu přidáte novou třídu a minimální verzi metody, která alespoň umožní úspěšné sestavení testu. Nejrychlejší způsob, jak to udělat, je vygenerovat třídu a metodu zástupný procedura z vyvolání v testu.

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

Generování tříd a metod z testů

Nejprve vytvořte projekt, do kterého chcete přidat novou třídu, pokud ještě neexistuje.

Generování třídy

  1. Umístěte kurzor na příklad třídy, kterou chcete vygenerovat, LocalMathnapříklad a vyberte Rychlé akce a refaktoringy.
  2. V místní nabídce zvolte Generovat nový typ.
  3. V dialogovém okně Generovat typ nastavte Project na projekt knihovny tříd. V tomto příkladu je to Fabrikam.Math.

Vygenerování metody

  1. Umístěte kurzor na volání metody, například SquareRoot, a vyberte Rychlé akce a refaktoring.
  2. V místní nabídce zvolte Generate method 'SquareRoot'.

Spuštění prvního testu

Sestavte a spusťte test. Výsledek testu zobrazuje červený indikátor selhání a test se zobrazí v seznamu neúspěšných testů.

Snímek obrazovky Průzkumníka testů zobrazující jeden neúspěšný test

Proveďte jednoduchou změnu kódu:

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

Znovu spusťte test a projde.

Snímek obrazovky Průzkumníka testů jednotek s jedním úspěšným testem

Spuštění testů jednotek

Spuštění testů jednotek:

  • Výběr možnosti Spustit>všechny testy
  • Pokud je Průzkumník testů otevřený, zvolte Spustit nebo Spustit všechny testy v zobrazení.

Snímek obrazovky Průzkumníka testů s tlačítkem Spustit vše

Pokud se test zobrazí v části Neúspěšné testy, otevřete test, například poklikáním na název. Bod, kdy se test nezdařil, se zobrazí v editoru kódu.

  • Pokud chcete zobrazit úplný seznam testů, zvolte Zobrazit vše.

  • Pokud chcete zobrazit podrobnosti o výsledku testu, vyberte test v Průzkumníku testů.

  • Pokud chcete přejít na kód testu, poklikejte na test v Průzkumníku testů nebo v místní nabídce zvolte Otevřít test .

  • Pokud chcete ladit test, otevřete místní nabídku pro jeden nebo více testů a pak zvolte Ladit.

  • Pokud chcete testy spouštět na pozadí při každém sestavení řešení, vyberte šipku vedle ikony Nastavení a pak vyberte Spustit testy po sestavení. Nejprve se spustí testy, které dříve selhaly.

Souhlas s rozhraním

Sdílením obrazovky můžete spolupracovat s kolegy, kteří budou vaši komponentu používat. Kolega by mohl okomentovat, že řada funkcí by prošla předchozím testem. Vysvětlete, že tento test byl jen proto, abyste se ujistili, že název a parametry funkce jsou správné, a teď můžete napsat test, který zachycuje hlavní požadavek této funkce.

Spolupracujete s kolegy a píšete následující 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);
}

Tip

Pro tuto funkci použijete první vývoj testů, ve kterém nejprve napíšete test jednotek pro funkci, a pak napíšete kód, který bude test spokojit. V jiných případech není tento postup realistický, takže testy napíšete po napsání kódu. Je ale velmi důležité psát testy jednotek, ať už před nebo po kódu, protože udržují kód stabilní.

Červená, zelená, refaktoring...

Postupujte podle cyklu, ve kterém opakovaně napíšete test a potvrdíte, že selže, napíšete kód, aby byl test úspěšný, a pak zvažte refaktoring, který kód vylepšuje beze změny testů.

Červený

Spusťte všechny testy, včetně nového testu, který jste vytvořili. Po napsání jakéhokoli testu ho vždy spusťte, abyste měli jistotu, že selže, než napíšete kód, který ho předá. Pokud například zapomenete v některých testech, které napíšete, umístit kontrolní výrazy, zobrazí se výsledek selhání s jistotou, že když ho projdete, výsledek testu správně značí, že požadavek byl splněn.

Dalším užitečným postupem je nastavení spuštění testů po sestavení. Tato možnost spustí testy na pozadí pokaždé, když sestavíte řešení, takže budete mít nepřetržitou zprávu o stavu testu kódu. Možná vás zajímá, že tento postup může usnadnit reakci sady Visual Studio, ale k tomu dochází jen zřídka.

Snímek obrazovky Průzkumníka testů s jedním neúspěšným testem

Zelený

Napíše první pokus o kód metody, kterou vyvíjíte:

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;
    }

Znovu spusťte testy a všechny testy jsou úspěšné.

Snímek obrazovky Průzkumníka testů jednotek se dvěma úspěšnými testy

Refaktoring

Teď, když kód provádí svou hlavní funkci, podívejte se na kód a najděte způsoby, jak ho vylepšit, nebo usnadnit změnu v budoucnu. Počet výpočtů provedených ve smyčce můžete snížit:

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;
    }

Ověřte, že testy stále projdou.

Tipy

  • Každá změna, kterou provedete při vývoji kódu, by měla být refaktoring nebo rozšíření:

    • Refaktoring znamená, že testy nezměníte, protože nepřidáte nové funkce.
    • Rozšíření znamená přidání testů a provedení změn kódu, které jsou nezbytné k předání stávajících i nových testů.
  • Pokud aktualizujete stávající kód na požadavky, které se změnily, odstraníte také staré testy, které už nepředstavují aktuální požadavky.

  • Vyhněte se změnám testů, které už prošly. Místo toho přidejte nové testy. Zapisujte pouze testy, které představují skutečný požadavek.

  • Testy spusťte po každé změně.

... a opakujte

Pokračujte v řadě kroků rozšíření a refaktoringu a použijte seznam malých kroků jako hrubý průvodce. Za každým rozšířením nemusíte vždy provádět refaktoringový krok a někdy postupně provedete více než jeden krok refaktoringu. Testy jednotek ale vždy spustíte po každé změně kódu.

Někdy přidáte test, který nevyžaduje žádnou změnu kódu, ale tím se zvýší vaše jistota, že kód funguje správně. Chcete například zajistit, aby funkce fungovala v široké škále vstupů. Píšete další testy, například toto:

[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);
}

Tento test projde při prvním spuštění.

Snímek obrazovky Průzkumníka testů se třemi úspěšnými testy

Jen proto, abyste se ujistili, že tento výsledek není chybou, můžete dočasně do testu zavést malou chybu, aby se nepovede. Jakmile se zobrazí chyba, můžete ji znovu opravit.

Tip

Než test projdete, vždy proveďte selhání testu.

Výjimky

Teď přejděte k psaní testů pro výjimečné vstupy:

[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");
}

Tento test vloží kód do smyčky. Musíte použít tlačítko Zrušit v Průzkumníku testů. Tím se kód ukončí do 10 sekund.

Chcete se ujistit, že na buildovém serveru nešlo dojít k nekonečné smyčce. I když server při úplném spuštění omezuje časový limit, je to velmi dlouhý časový limit, který by způsobil značné zpoždění. Proto můžete do tohoto testu přidat explicitní časový limit:

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

Explicitní časový limit způsobí selhání testu.

Aktualizujte kód tak, aby se zabýval tímto výjimečným případem:

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

Regrese

Nový test projde, ale dojde k regresi. Test, který se použil k předání, se teď nezdaří:

Snímek obrazovky s testem jednotek, který dříve proběhl úspěšně

Vyhledejte a opravte chybu:

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

Po opravení budou všechny testy úspěšné:

Snímek obrazovky Průzkumníka testů jednotek se čtyřmi úspěšnými testy

Tip

Ujistěte se, že všechny testy projdou po každé změně, kterou v kódu provedete.

Pokrytí kódu

V intervalech během práce a nakonec před vrácením kódu se změnami získejte sestavu pokrytí kódu. To ukazuje, kolik kódu vaše testy vycvižovaly.

Cílem vašeho týmu je pokrytí alespoň 80 %. Uvolní tento požadavek na vygenerovaný kód, protože pro tento typ kódu může být obtížné dosáhnout vysokého pokrytí.

Dobré pokrytí není zárukou, že byla otestována úplná funkčnost komponenty a nezaručuje, že kód bude fungovat pro každý rozsah vstupních hodnot. Nicméně existuje poměrně úzká korelace mezi pokrytím řádků kódu a pokrytím prostoru chování komponenty. Proto dobré pokrytí posiluje důvěru týmu, že testují většinu chování, které by měli.

Pokud chcete získat sestavu pokrytí kódu, vyberte v nabídce Visual Studio Test možnost Analyzovat pokrytí kódu pro všechny testy. Všechny testy se spustí znovu.

Snímek obrazovky s výsledkem pokrytí kódu a tlačítkem Zobrazit barvu

Když v sestavě rozbalíte součet, ukáže se, že kód, který vyvíjíte, má úplné pokrytí. To je velmi uspokojivé, protože důležité skóre je pro kód, který se testuje. Odhalené části jsou ve skutečnosti v samotných testech.

Když přepnete tlačítko Zobrazit barvu pokrytí kódu, uvidíte, které části testovacího kódu nebyly cvičení. Kód, který nebyl použit v testech, je zvýrazněn oranžový. Tyto části jsou ale pro pokrytí nedůležité, protože jsou v testovacím kódu a budou použity pouze v případě, že se zjistí chyba.

Pokud chcete ověřit, že konkrétní test dosáhne konkrétních větví kódu, můžete nastavit zobrazení barvy pokrytí kódu a pak spustit jeden test pomocí příkazu Spustit v místní nabídce.

Kdy jste hotovi?

Pokračujte v aktualizaci kódu v malých krocích, dokud nebudete spokojeni:

  • Všechny dostupné testy jednotek jsou úspěšné.

    V projektu s velmi velkou sadou testů jednotek může být nepraktické, aby vývojář čekal, až budou všichni spuštěni. Místo toho projekt provozuje vrátnou službu vrácení se změnami, ve které se všechny automatizované testy spouští pro každou sadu odložených odložených změn před sloučením do zdrojového stromu. Vrácení se změnami se odmítne, pokud se spuštění nezdaří. To umožňuje vývojářům spouštět minimální sadu testů jednotek na vlastních počítačích a pak pokračovat v jiné práci, aniž by riskovali narušení sestavení. Další informace najdete v tématu Použití zamknutého procesu vrácení se změnami k ověření změn.

  • Pokrytí kódu splňuje standard týmu. 75 % je typickým požadavkem na projekt.

  • Testy jednotek simulují všechny aspekty požadovaného chování, včetně typických i výjimečných vstupů.

  • Váš kód je snadno pochopitelný a rozšířitelný.

Jakmile jsou splněna všechna tato kritéria, jste připraveni zkontrolovat kód do správy zdrojového kódu.

Principy vývoje kódu pomocí testů jednotek

Při vývoji kódu použijte následující principy:

  • Vyvíjejte testy jednotek společně s kódem a často je spouštět během vývoje. Testy jednotek představují specifikaci vaší komponenty.
  • Neměňte testy jednotek, pokud se požadavky nezměnily nebo testy nebyly chybné. Postupně přidávat nové testy, jakmile rozšíříte funkčnost kódu.
  • Snažte se, aby testy pokrýval alespoň 75 % kódu. Prohlédněte si výsledky pokrytí kódu v intervalech a před vrácením zdrojového kódu se změnami.
  • Zkontrolujte testy jednotek společně s kódem, aby se spouštěly průběžnými nebo běžnými sestaveními serveru.
  • Pokud je to praktické, pro každou část funkčnosti nejprve napište test jednotek. Udělejte to před vývojem kódu, který ho splňuje.

Vrácení změn se změnami

Před vrácením změn se změnami znovu sdílejte obrazovku s kolegy, aby mohli neformálně a interaktivně zkontrolovat, co jste vytvořili. Testy jsou i nadále zaměřeny na vaši diskuzi s kolegy, kteří se primárně zajímají o to, co kód dělá, a ne na tom, jak funguje. Tito kolegové by měli souhlasit s tím, že to, co jste napsali, splňuje jejich potřeby.

Zkontrolujte všechny provedené změny, včetně testů i kódu, a přidružte je k dokončeným úkolům. Vrácení se změnami se zařadí do fronty automatizovaného systému sestavení týmu, který ověří změny pomocí procesu sestavení CI týmu. Tento proces sestavení pomáhá týmu minimalizovat chyby v základu kódu sestavením a testováním v čistém prostředí odděleném od vývojových počítačů, a to každou změnou, kterou tým provede.

Po dokončení sestavení se zobrazí oznámení. V okně výsledků sestavení uvidíte, že sestavení bylo úspěšné a všechny testy byly úspěšné.

Vrácení změn se změnami

  1. Na stránce Moje práce v Team Exploreru vyberte Vrátit se změnami.

    Snímek obrazovky s vrácením se sem ze služby Moje práce

  2. Na stránce Čekající změny se ujistěte, že:

    • Všechny relevantní změny jsou uvedeny v zahrnutých změnách.
    • Všechny relevantní pracovní položky jsou uvedené v souvisejících pracovních položkách.
  3. Zadejte komentář, který týmu pomůže pochopit účel těchto změn, když se podívá na historii správy verzí změněných souborů a složek.

  4. Zvolte Vrátit se změnami.

    Snímek obrazovky s vrácením se změnami čekajících změn

Průběžná integrace kódu

Další informace o definování procesu průběžné integrace sestavení naleznete v tématu Nastavení sestavení CI. Po nastavení tohoto procesu sestavení se můžete rozhodnout, že budete upozorněni na výsledky týmových buildů.

Snímek obrazovky se stránkou Moje buildy s úspěšným sestavením

Další informace najdete v tématu Spuštění, monitorování a správa sestavení.

Další kroky