Pro uživatele článek napsat nový kód
Jste nový uživatel správy životního cyklu aplikací (ALM) systému Visual Studio a serveru Team Foundation Server (TFS)?Zajímá vás, jak vy a váš tým můžete získat maximální výhody nejnovější verze těchto nástrojů k vytvoření vaší aplikace?
Pak věnujte několik minut tomuto dvoudílnému návodu, který vás krok za krokem provede jedním dnem v životě Petra a Julie, dvou vývojářů ve fiktivní společnosti Fabrikam Fiber, která poskytuje kabelovou televizi a související služby.Uvidíte příklady použití systému Visual Studio a serveru TFS k rezervování a aktualizaci kódu, pozastavení práce při přerušení, zažádání o přezkoumání kódu, vrácení vašich změn a provádění dalších úkolů.
Uvedení do děje
Tento tým nedávno začal používat systém Visual Studio a server Team Foundation pro správu životního cyklu aplikací (ALM).Nastavili si vlastní server a klientské počítače, vytvořili nevyřízené položky, naplánovali iteraci a dokončili další plánování nezbytné před zahájením vývoje jejich aplikace.
Přehled této kapitoly
Petr krátce prohlédne své nevyřízené položky a vybere si úkol, na kterém dnes bude pracovat.Napíše testy částí pro kód, který má v úmyslu vyvinout.Tyto testy spustí obvykle několikrát za hodinu, postupně napíše podrobnější testy a poté kód, který je splní.S kolegy, kteří budou používat tuto metodu, často diskutuje rozhraní svého kódu.
[!POZNÁMKA]
Funkce Moje práce a Pokrytí kódu popsané v tomto tématu jsou k dispozici pouze v systémech Visual Studio Premium a Visual Studio Ultimate.
V tomto tématu
Prohlédnutí osobních nevyřízených položek a příprava úkolů, na kterých se začne pracovat
Vytvoření prvního testu částí
Vytvoření zástupce nového kódu
Spuštění prvního testu
Odsouhlasení rozhraní API
Červená, zelená, refaktorování...
Pokrytí kódu
Kdy jsme hotovi?
Vrácení změn
Prohlédnutí osobních nevyřízených položek a příprava úkolů, na kterých se začne pracovat
Petr v Průzkumníku týmových projektů otevře stránku Moje práce.Tým odsouhlasil, že během aktuálního sprintu bude Petr pracovat na úkolu Vyhodnocení stavu faktury, položce s nejvyšší prioritou v nevyřízených položkách produktu.Peter se rozhodne začít s úkolem Implementace matematických funkcí, podřízenou úlohou položky s nejvyšší prioritou v nevyřízených položkách.Tento úkol přetáhne ze seznamu Dostupné pracovní položky do seznamu Pracovní položky v průběhu & změny.
Chcete-li prohlédnout osobní nevyřízené položky a připravit úkoly, na kterých začnete pracovat
V Průzkumníku týmových projektů:
Pokud již nejste připojeni k týmovému projektu, na kterém chcete pracovat, připojte se k týmovému projektu.
Vyberte Domů a poté zvolte Moje práce.
Na stránce Moje práce přetáhněte úkol ze seznamu Dostupné pracovní položky do oddílu Pracovní položky v průběhu.
Úkol lze také vybrat ze seznamu Dostupné pracovní položky a poté zvolit Spustit.
Návrh dílčího plánu práce
Petr kód obvykle vyvíjí v sérii menších kroků.Každý krok obvykle netrvá déle než hodinu, může také trvat jen deset minut.V každém kroku napíše nový test částí a změní kód, který vyvíjí tak, aby kromě již hotových testů splnil i tento nový test.Někdy před změnou kódu napíše nový test a někdy změní kód před vytvořením testu.Někdy provede refaktorování.To znamená, že vylepší kód bez přidání nových testů.Nikdy nemění splněný test, pokud se nerozhodne, že nesprávně představuje požadavek.
Na konci každého malého kroku spustí všechny testy částí, které jsou relevantní pro tuto oblast kódu.Tento krok nepovažuje za dokončený, dokud není každý test splněn.
Neprovede vrácení se změnami na server Team Foundation Server, dokud nedokončí celý úkol.
Petr napíše hrubý plán této série malých kroků.Ví, že přesné podrobnosti a pořadí pozdějších kroků se během jeho práce pravděpodobně změní.Zde je jeho počáteční seznam kroků pro tuto konkrétní úlohu:
Vytvořit zástupnou testovací metodu, to znamená pouze podpis této metody.
Splnit jeden konkrétní typický případ.
Otestovat širší rozsah.Ujistit se, že kód odpovídá správně pro velký rozsah hodnot.
Výjimka při negativních hodnotách.Řádně se vypořádat s nesprávnými parametry.
Pokrytí kódu.Ujistit se, že nejméně 80 % kódu je otestováno pomocí testů částí.
Někteří jeho kolegové píší tento druh plánu v komentářích jejich kódu testu.Jiní si svůj plán pouze zapamatují.Petr považuje za užitečné napsat svůj seznam kroků do pole Popis pracovní položky Úkol.Pokud bude muset dočasně přejít na důležitější úkol, bude vědět, kde tento seznam najít, když se vrátí zpět.
Vytvoření prvního testu částí
Petr začíná vytvořením testu částí.Začíná testem částí, protože chce napsat příklad kódu, který používá jeho novou třídu.
Je to první test částí knihovny tříd, kterou testuje a tak vytvoří nový projekt testů částí.Otevře dialogové okno Nový projekt, vybere Visual C#, Test a poté Projekt testů částí.
Projekt testů částí obsahuje soubor jazyka C#, do kterého si může napsat svůj příklad.V této fázi chce jen znázornit, jak bude jedna z jeho nových metod volána:
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);
}
}
}
Tento příklad napíše do testovací metody, protože v době psaní kódu, chce funkční příklad.
Chcete-li vytvořit projekt a metody testů částí
Obvykle byste měli vytvořit nový projekt testů pro každý projekt, který je testován.Pokud testovací projekt již existuje, lze pouze přidat nové testovací metody a třídy.
Tento postup používá rozhraní Unit Test Framework systému Visual Studio, ale lze také použít rozhraní od jiných poskytovatelů.Průzkumník testů funguje stejně dobře s jinými rozhraními, pokud nainstalujete příslušný adaptér.
Vytvořte testovací projekt, pokud již neexistuje.
- V dialogovém okně Nový projekt zvolte jazyk, jako je jazyk Visual Basic, Visual C++ nebo Visual C#.Vyberte Test a poté Projekt testů částí.
Přidejte vaše testy do třídy testů, která je k dispozici.Každý test částí je jedna metoda.
Každý test částí musí mít atribut TestMethod a měl by být bez parametrů.Metoda testu částí může mít libovolný název:
[TestMethod] public void SignatureTest() {...}
<TestMethod()> Public Sub SignatureTest() ... End Sub
Každá testovací metoda by měla pomocí volání nějaké metody třídy Assert určit, zda je splněna nebo nesplněna.Obvykle se ověří, zda jsou si očekávané a skutečné výsledky operace rovny:
Assert.AreEqual(expectedResult, actualResult);
Assert.AreEqual(expectedResult, actualResult)
Vaše testovací metody mohou volat jiné běžné metody, které nemají atribut TestMethod.
Testy lze uspořádat do více než jedné třídy.Každá třída musí mít atribut TestClass.
[TestClass] public class UnitTest1 { ... }
<TestClass()> Public Class UnitTest1 ... End Class
Další informace o vytvoření testů částí v jazyce Visual C++ naleznete v tématu Zápis testů částí pro C/C++ s infrastrukturou testování částí Microsoft Unit Testing Framework pro C++.
Vytvoření zástupce nového kódu
Dále Petr pro svůj nový kód vytvoří projekt knihovny tříd.Nyní existuje projekt pro kód ve vývoji a projekt pro testy částí.Do projektu kódu ve vývoji přidá referenci na projekt testů.
V tomto novém projektu přidá novou třídu a minimální verzi metody, která testy umožní alespoň úspěšně sestavit.Nejrychlejší způsob jak to udělat je vygenerovat zástupce třídy a metody pomocí vyvolání v testu.
public double SquareRoot(double p)
{
throw new NotImplementedException();
}
Chcete-li vygenerovat třídy a metody z testů
Nejprve vytvořte projekt, kam chcete tuto novou třídu přidat, pokud již neexistuje.
Chcete-li vygenerovat třídu
Umístěte kurzor na název třídy, kterou chcete vytvořit, například LocalMath. Z místní nabídky vyberte Generovat kód, Nový typ.
V dialogovém okně Nový typ nastavte pole Projekt na projekt knihovny tříd.V tomto příkladu je to Fabrikam.Math.
Chcete-li vygenerovat metodu
- Umístěte kurzor na volání metody, například SquareRoot.Z místní nabídky vyberte Generovat kód, Zástupná metoda.
Spuštění prvního testu
Petr tento test sestaví a spustí stisknutím kombinace kláves CTRL + R, T. Výsledek testu zobrazí červený indikátor označující, že se test nezdařil a tento test se zobrazí v seznamu Neúspěšné testy.
V kódu provede jednoduchou změnu:
public double SquareRoot(double p)
{
return 0.0;
}
Spustí test znovu a je úspěšný:
Chcete-li spustit testy částí
V nabídce Test zvolte Spustit, Všechny testy.
nebo
Pokud je Průzkumník testů otevřen, zvolte Spustit všechny.
nebo
Umístěte kurzor do testovacího souboru kódu a stiskněte kombinaci kláves CTRL + R, T.
Pokud je test zobrazen v seznamu Neúspěšné testy.
Otevřete test, například dvojitým kliknutím na jeho název.
Je zobrazen bod, ve kterém se test nezdařil.
Chcete-li zobrazit úplný seznam testů, zvolte Zobrazit všechny.Chcete-li se vrátit na souhrn, zvolte zobrazení Domů.
Chcete-li zobrazit podrobnosti výsledku testu, vyberte tento test v Průzkumníku testů.
Chcete-li přejít na kód testu, dvakrát klikněte na tento test v Průzkumníku testů nebo zvolte možnost Otevřít test z místní nabídky.
Chcete-li ladit test, otevřete místní nabídku jednoho nebo více testů a zvolte možnost Ladit vybrané testy.
Chcete-li spustit testy na pozadí při každém sestavení řešení, přepněte na možnost Spustit testy po sestavení.Testy, které se dříve nezdařily jsou spuštěny jako první.
Odsouhlasení rozhraní
Petr pomocí služby Lync zavolá své kolegyni Julii a sdílí s ní svou obrazovku.Julie bude používat jeho součást.Petr jí ukáže svůj první příklad.
Julie si myslí, že je příklad v pořádku, ale dodává: „Tímto testem projde mnoho funkcí.“
Petr odpoví: „První test jen ujišťuje, že jsou název a parametry funkce správné.Nyní můžeme napsat test, který zachycuje hlavní požadavek této funkce.“
Společně napíší 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 Petr používá techniku Test First Development, kdy nejprve vytvoří testy částí pro danou funkci a poté napíše kód, který splní požadavky tohoto testu.V ostatních případech zjistil, že tento postup není reálný, tak místo toho píše testy až poté, co napíše kód.Ale považuje za velmi důležité testy částí psát, ať už před nebo po napsání kódu, protože udržují stabilní kód.
Červená, zelená, refaktorování...
Petr následuje cyklus, v němž opakovaně napíše test a potvrdí, že selhal, napíše kód, který testem projde a poté zváží refaktorování, což znamená vylepšování kódu bez změny testů.
Červená
Petr stisknutím kombinace kláves CTRL + R, T spustí nový test, který vytvořil s Julií.Poté co napíše jakýkoli test, jej vždy spustí a ujistí se, že selže, před tím než napíše kód, který jej má splnit.Toto je praxe, kterou se naučil poté, co zapomněl umístit kontrolní výrazy v některých testech, které napsal.Zobrazením výsledku selhání se ujistí, že když test projde, výsledek testu skutečně znamená, že byl požadavek splněn.
Jiným osvědčeným postupem je nastavení možnosti Spustit testy po sestavení.Tato možnost spustí testy na pozadí při každém sestavení řešení, aby jste měli neustálý přehled o stavu testů vašeho kódu.Petr měl nejprve podezření, že to může zpomalit reakce systému Visual Studio, ale zjistil, že k tomu dojde jen zřídka.
Zelená
Petr napsal první pokus kódu metody, kterou vyvíjí:
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;
}
Petr znovu spustí testy a všechny tyto testy jsou úspěšné:
Refaktorování
Nyní, když kód provádí svou hlavní funkci, Petr prohlédne kód, aby nalezl způsoby, díky kterým kód poskytne lepší výkon nebo usnadní změny v budoucnu.Uvědomuje si, že lze snížit počet výpočtů provedených ve smyčce:
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ěří, že kód stále projde testy:
Tip
Všechny změny provedené při vývoji kódu by měly být buď refaktoring nebo rozšíření:
-
Refaktoring znamená, že neměníte testy, protože nepřidáváte žádné nové funkce.
-
Rozšíření znamená přidání testů a provedení změn kódu, které jsou nezbytné pro splnění stávajících i nových testů.
Jestliže aktualizujete existující kód podle změněných požadavků, odstraňte také staré testy, které již nepředstavují aktuální požadavky.
Předejděte změnám v testech, které jsou již splněny.Namísto toho přidejte nové testy.Pište pouze testy, které představují skutečný požadavek.
Testy spusťte po každé změně.
A opakujte
Petr pokračuje v sérii kroků rozšíření a refaktoringu pomocí svého seznamu, který mu slouží jako hrubé vodítko.Krok refaktoringu neprovádí po každém rozšíření a někdy provede více kroků refaktoringu za sebou.Testy částí, ale spouští vždy po každé změně kódu.
Někdy přidá test, který nevyžaduje žádnou změnu kódu, pouze se ujišťuje, že jeho kód funguje správně. Například se chce ujistit, že funkce pracuje s širší škálou vstupů.Napíše více testů, jako je tento:
[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 při prvním spuštění prošel:
Aby se ujistil, že tento výsledek není chybný, dočasně do svého testu přidá malou chybu, aby se nezdařil.Po zjištění této chyby test zase opraví.
Tip
Předtím než test necháte projít, vždy test nechte selhat.
Výjimky
Petr nyní přejde k napsání testů pro mimořádné 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 kód vloží do smyčky.Musí použít tlačítko Zrušit v Průzkumníku testů.To kód ukončí během 10 sekund.
Petr se chce ujistit, že na serveru sestavení nemůže dojít k nekonečné smyčce.Přestože server úplnému spuštění ukládá časový limit, je tento časový limit velmi dlouhý a mohl by způsobit značné zpoždění.Proto svému testu přidá explicitní časový limit:
[TestMethod, Timeout(1000)]
public void RootTestNegativeInput()
{...
Díky explicitnímu časovému limitu se test nezdaří.
Petr poté aktualizuje kód tak, aby řešil tento výjimečný případ:
public double SquareRoot(double x)
{
if (x <= 0.0)
{
throw new ArgumentOutOfRangeException();
}
Regrese
Tyto nové testy prošly, ale existuje zde regrese.Test, který dříve prošel se nyní nezdaří:
Petr najde a opraví chybu:
public double SquareRoot(double x)
{
if (x < 0.0) // not <=
{
throw new ArgumentOutOfRangeException();
}
Poté, co tuto chybu opraví, jsou všechny testy úspěšné:
Tip
Přesvědčte se, že každý test po každé změně provedené v kódu projde.
Pokrytí kódu
V intervalech během své práce a nakonec před vrácením kódu se změnami Petr obdrží sestavu o pokrytí kódu.Ta popisuje, jak velká část kódu byla zkoušena jeho testy.
Petrův tým je zaměřen na pokrytí nejméně 80 %.Tento požadavek pro vygenerovaný kód zmírňují, protože pro tento typ kódu může být obtížné dosáhnout vysokého pokrytí.
Dobré pokrytí není zárukou toho, že byla otestována plná funkčnost této součásti a nezaručuje, že kód bude fungovat se všemi rozsahy vstupních hodnot.Nicméně existuje poměrně úzká souvislost mezi pokrytím řádků kódu a pokrytím chování komponenty.Proto dobré pokrytí v týmu posiluje důvěru, že testují většinu chování, které by měli.
Chcete-li získat sestavu pokrytí kódu, v nabídce Testy zvolte Spustit, Analyzovat pokrytí kódu pro všechny testy.Poté znovu spusťte všechny testy.
Petr získá celkové pokrytí 86 %.Když v sestavě rozbalí toto celkové pokrytí, ukáže se, že kód, který vyvíjí má pokrytí 100 %.To je velmi uspokojivé, protože toto důležité skóre se týká testovaného kódu.Nepokryté oddíly jsou skutečně v testech samotných.Přepnutím tlačítka Zobrazit barevné označení pokrytí kódu, může Petr vidět, které části kódu testu nejsou zkoušeny.Rozhodne se však, že tyto oddíly nejsou pro pokrytí důležité, protože jsou v kódu testu a měly by být použity pouze tehdy, pokud je detekována chyba.
Chcete-li ověřit, že určitý test dosáhne určitých větví kódu, lze nastavit Zobrazit barevné označení pokrytí kódu a poté spustit jeden test pomocí příkazu Spustit v místní nabídce.
Kdy jsme hotovi?
Petr nadále v malých krocích aktualizuje kód, dokud není ujištěn, že:
Všechny dostupné testy částí projdou.
V projektu s velmi velkými sadami testů částí může být pro vývojáře čekání na spuštění všech testů nepraktické.Místo toho projekt poskytuje službu ověřovaného vrácení se změnami, ve kterém jsou pro každou sadu změn spuštěny všechny automatizované testy, předtím než je sloučena se zdrojovým stromem.Vrácení se změnami je odmítnuto, pokud se testy nezdaří.To vývojáři umožňuje na vlastním počítači spouštět pouze minimální sadu testů částí a poté pokračovat v další práci bez rizika rozbití sestavení.Další informace naleznete v tématu Použití procesu sestavení s hlídaným vrácením se změnami pro ověření změn.
Pokrytí kódem splňuje standard týmu. 75 % je požadavek typického projektu.
Jeho testy částí simulují všechny aspekty požadovaného chování, včetně typických a mimořádných vstupů.
Jeho kódu lze snadno porozumět a rozšiřovat jej.
Při splnění všech těchto kritérií, je Petr připraven k vrácení kódu se změnami do správy zdrojového kódu.
Zásady vývoje kódu s testy částí
Petr při vývoji kódu uplatňuje následující zásady:
Vyvíjí testy částí spolu s kódem a během vývoje je často spouští.Testy částí představují určitou specifikaci vaší komponenty.
Neměňte testy částí, pokud se nezměnily požadavky nebo jsou tyto testy nesprávné.Jak rozšiřujete funkce kódu, postupně přidávejte nové testy.
Mějte za cíl nejméně 75 % pokrytí kódu testy.V intervalech a před vrácením zdrojového kódu se změnami si prohlížejte výsledky pokrytí kódu.
Vaše testy částí vracejte spolu se změnami kódu, aby byly spuštěny průběžnými nebo pravidelnými sestaveními serveru.
Pokud je to proveditelné, pro každou část funkce nejdříve napište test částí.Proveďte to předtím, než vytvoříte kód, který jej splní.
Vrácení změn
Před vrácením svých změn, Petr opět použije službu Lync pro sdílení své obrazovky s kolegyní Julií, aby s ním mohla neformálně a interaktivně zkontrolovat, co vytvořil.Tyto testy jsou nadále předmětem jejich diskuse, protože Julii především zajímá, co kód dělá a ne jak funguje.Julie souhlasí s tím, že to co Petr napsal, splňuje její potřeby.
Petr vrátí všechny změny, které provedl, což zahrnuje oboje, testy i kód, a spojí je s dokončeným úkolem.Vrácení se změnami je zařazeno do fronty systému automatizovaného sestavení týmu k ověření jeho změn pomocí procesu sestavení kontinuální integrace.Tento proces sestavení týmu pomáhá minimalizovat chyby v jejich kódu pomocí sestavení a testování každé provedené změny v čistém prostředí nezávisle na jejich vývojových počítačích.
Petr je po dokončení sestavení upozorněn.V okně výsledků sestavení uvidí, zda bylo sestavení úspěšné a všechny testy prošly.
Chcete-li vrátit provedené změny
V řádku nabídek zvolte Zobrazení a Průzkumník týmových projektů.
V Průzkumníku týmových projektů vyberte Domů a poté vyberte Moje práce.
Na stránce Moje práce zvolte Vrátit se změnami.
Prohlédněte si obsah stránky Čekající změny a ujistěte se, že:
Všechny důležité změny jsou uvedeny v části Zahrnuté změny
Všechny relevantní pracovní položky jsou uvedeny v části Související položky práce.
Zadejte Komentář, aby vašemu týmu pomohl pochopit účel těchto změn při prohlížení v historii řízení verzí změněných souborů a složek.
Vyberte Vrátit se změnami.
Chcete-li kód kontinuálně integrovat
Další informace o způsobu definování procesu sestavení kontinuální integrace naleznete v tématu Nastavení sestavení s nepřetržitou integrací (CI).Po nastavení tohoto procesu sestavení lze dostávat oznámení o výsledcích sestavení týmu.
Další informace naleznete v tématu Spuštění, monitorování a správa sestavení.
Další (Pozastavení práce, oprava chyby a vedení přezkoumání kódu)