Unit Testen in Visual Studio 2005

Unit Testen in Visual Studio 2005

Test-driven development (TDD) is een techniek voor het ontwerpen en ontwikkelen van software. Het streven van TDD is het creëren van software elementen die relatief onafhankelijk van elkaar kunnen functioneren. Dat kunnen we bereiken door een reeks testen, zogeheten unit testen, te schrijven die op ieder moment uitgevoerd kunnen worden en rapporteren over de juiste werking van de geschreven programmacode. In het bredere raamwerk van Agile ontwikkelmethoden neemt TDD een essentiële plaats in.

In dit artikel worden de mogelijkheden van deze techniek zoals deze in Visual Studio Team System zijn ondergebracht onder de loep genomen.

Voordelen van test-driven development

Voor we in Visual Studio duiken kijken we eerst naar de voordelen van test-driven development. Waarom zouden we deze techniek gebruiken?

Het komt de laatste tijd steeds minder voor dat we een software-ontwikkelproject beginnen met een helder en ondubbelzinning functioneel en technisch ontwerp. Dat is meestal het gevolg van incomplete requirements, gebrek aan tijd bij de architecten en opdrachtgevers die pas tegen het einde van het project weten hoe ze het willen hebben. Een nachtme … ehm … uitdaging voor projectleiders, maar niet voor ontwikkelaars. Tenminste, dat is wat test-gedreven ontwikkelen belooft. Deze manier van ontwikkelen gaat uit van een drietal taken:

  1. het schrijven van een test;
  2. het schrijven van programmacode om de test te doen slagen en
  3. het herschrijven van programmacode om het efficiënter, flexibeler en beter te begrijpen te maken

Deze drie stappen worden voortdurend herhaald. In theorie worden alle testen bij iedere iteratie opnieuw uitgevoerd om te beoordelen of alles nog werkt. Er is op deze manier telkens maar een korte tijd tussen het ontwerpen, ontwikkelen en testen van het programma. Uiteindelijk, zo is de verwachting, verbetert het programmaontwerp en de programmacode. Een test in dit kader noemen we een unit test. 

Veel moderne unit test frameworks zijn gebaseerd op het framework van Kent Beck. Dit framework is geschreven in Smalltalk en bestaat nog steeds, alhoewel er in de loop van de tijd meerdere revisies zijn geweest. Later is dit framework geport naar Java en werd toen jUnit genoemd. Daarna zijn er implementaties gekomen in C++, VB, Python, Perl, etc.

Unit Test functies in Visual Studio 2005

Sinds enige tijd is NUnit (www.nunit.org) beschikbaar voor de Visual Studio omgeving, maar met de komst van Visual Studio 2005 Team System zijn testen een standaard onderdeel van het ontwikkelgereedschap geworden. Helaas beschikken niet alle edities van Visual Studio 2005 standaard over unit test faciliteiten. Hieronder staat een overzicht van de test-mogelijkheden per editie:

Visual Studio 2005 Editie Unit Testen Load Testing, Manual Testing, Test Case Management, en Web Testing
Express nee Nee
Standard nee Nee
Professional nee Nee
Team System for Software Architects nee Nee
Team System for Software Developers ja Nee
Team System for Software Testers ja Ja
Team Suite ja Ja

Met uitzondering van de Express-versies kunnen ook andere edities van Visual Studio 2005 voorzien worden van unit test mogelijkheden via de add-ins TestDriven.NET (www.testdriven.net) en NUnit (www.nunit.org). Zoals gezegd, dit artikel behandelt de mogelijkheden van unit testen in Visual Studio Team System (VSTS).

Alhoewel de structuur en voorbeelden gebaseerd zijn op VSTS is een vertaling naar NUnit ook te maken:

NUnit Framework Concept VS 2005 Equivalent Omschrijving
Test TestMethod Dit zijn je testen. Het zijn methoden in het test-project met instructies die controleren op het verwachte resultaat van de programmacode.
Test Fixture TestClass Een logische groepering van één of enkele testen. Deze groepering vindt plaats in een klasse.
Test Suite Test List Een logische groepering van meerdere test-klassen. Dit is het test-project.
Test Runner VS 2005 VSTS Unit Testing Framework Een programma met een gebruikersinterface (ook vanaf de commandoregel) voor het uitvoeren en rapporteren van de testen. We gebruiken in dit artikel Visual Studio 2005 Team System als de test runner.

Voorbeeldproject: een Task-klasse

Als voorbeeld hanteren we een klasse waarmee we taken (Tasks) kunnen bijhouden. Wanneer we TDD strikt hanteren, zouden we eerst een test moeten schrijven waarin we al wat gedrag en eigenschappen aanspreken. Zonder een eerste klasse is dat echter vrij lastig. Het project zou niet eens compileren. Bovendien kan Visual Studio ons helpen bij het maken van de juiste testen. Als we de projectstructuur eenmaal in de basis op orde hebben, kunnen we regels van TDD weer nauwgezet volgen.

We beginnen met een globaal idee van de Task-klasse (zie figuur 1). Dan heb je een idee van het verwachte eindresultaat. In de loop van het artikel wordt deze klasse gevuld en van een implementatie voorzien.

Fig. 1: De Task-klasse en TaskStatus-enumeratie

We zorgen er voor dat alle test-programmacode in een apart project wordt bewaard. Het is immers goed gebruik om het uiteindelijke programma niet te vervuilen met testinstructies.

Voor het voorbeeld maken we gebruik van Visual Basic als ontwikkeltaal. De unittest-mogelijkheden in Visual Studio zijn echter identiek voor Visual C#. Buiten de syntax kunnen de stappen dus zonder meer ook door C# programmeurs gevolgd worden.

Stap 1: Opzet projectstructuur

We beginnen met het opzetten van de projectstructuur. Kies in Visual Studio File > New  > Project. Kies het template voor Class Library onder de Visual Basic projecttypes. Zorg er ook voor dat de optie Create Directory for Ssolution is aangevinkt. Daarmee hebben we straks de mogelijkheid om het testproject in een aparte folder te plaatsen. Als we deze optie niet selecteren, wordt het testproject in een subfolder van het hoofdproject geplaatst. Geeft zowel de solution als het project de naam TaskOrganizer.

Hernoem het bestand Class1.vb naar Task.vb. Wanneer je dit doet, wordt de klasse Class1 hernoemd in Task, maar je wordt wel om een bevestiging gevraagd. In de Task-klasse plaatsen we een constructor met een naam als parameter. Zodra deze constructor is ingevoerd, kunnen we er een test voor genereren.

Fig. 2: Via het context-menu kunnen we een test genereren

Voor we ook maar iets implementeren in de Task-klasse, gaan we eerst een test creëren. Dit kan je doen via de rechtermuisknop op de Task-constructor. Dan kies je Create Unit Tests…. Nu wordt een scherm getoond om de unit tests in een apart project onder te brengen. Hier kies je Visual Basic, maar Visual C# is natuurlijk ook mogelijk, net als Visual C++. Geef als naam TaskOrganizerTests en kies Create.

Fig. 3: Via een dialoogscherm wordt een testproject toegevoegd aan de solution

Automatisch worden enkele bestanden toegevoegd aan de solution. Ook het project TaskOrganizerTest is al voorzien van twee bestanden. De onderstaande tabel geeft het doel van ieder bestand weer.

Bestandsnaam Doel
AuthoringTest.txt Een tekstbestand met instructies over het schrijven van testen en het toevoegen van nieuwe testen aan het project.
TaskTest.vb Bevat een gegenereerde test voor het testen van de Task-constructor met wat instructies voor het initialiseren en opruimen.
TaskOrganizer.vsmdi Hiermee bestuur je de Test Manager waarmee je de testen in de solution kunt bekijken. Met de Test Manager kan een hiërarchische lijst samengesteld worden. Wanneer je tientallen of honderden testen in het project hebt zitten, kun je er zo voor kiezen om een subset van de testen uit te voeren.
localtestrun.testrunconfig Je kunt ook de manier waarop de testen worden uitgevoerd manipuleren door instellingen in de test-run configuratie. Deze instellingen worden bewaard in een bestand met de extensie .testrunconfig. Je kunt meerdere configuratiebestanden maken en selecteren voor het uitvoeren van de test.

Naast de toegevoegde bestanden bevat het testproject ook referenties naar Microsoft.VisualStudio.QualityTools.UnitTestFramework en het TaskOrganizer-project. De eerste referentie wijst naar de assembly met het test-framework waar Visual Studio mee werkt.

We kunnen nu ook zien hoe de testmethode er uit ziet. In het bestand TaskTest.vb zien we onder meer:

'''


'''A test for New(ByVal String)
'''

_
  Public Sub ConstructorTest()
    Dim name As String = Nothing
    'TODO: Initialize to an appropriate value
    Dim target As Task = New Task(name)
    'TODO: Implement code to verify target
    Assert.Inconclusive(_
      "TODO: Implement code to verify target")
  End Sub

De precieze code die Visual Studio genereert zal variëren op grond van de methode die getest wordt. Voor methoden die niet publiek zijn, wordt bijvoorbeeld met behulp van reflection een reeks instructies samengesteld om ook deze te kunnen testen.

Stap 2: De testen (her)schrijven

We zien een tweetal attributen terugkomen in de klasse waar de testmethoden worden geplaatst. Een methode die in de test moet worden uitgevoerd wordt aangeduid met de TestMethod()-attribuut. De klasse zelf krijgt het attribuut TestClass(). Beide attributen zijn terug te vinden in de Microsoft.VisualStudio.QualityTools.UnitTesting.Framework-namespace. Wanneer de testrun plaatsvindt kan met behulp van reflection gekeken worden welke klassen de testmethoden bevat en welke methoden getest moeten worden. Een essentieel aspect van de test is dat enkel methoden worden getest die geen parameters bevatten. De compiler controleert dit overigens niet.

De testmethode ConstructorTest() creëert een Task-object en meldt dan dat de test geen uitsluitsel geeft. Hiermee wordt gemeld dat de test niet mislukt is, of geslaagd, maar dat dit eenvoudigweg niet vastgesteld kan worden. Hiervoor wordt de instructie Assert.Inconclusive gebruikt. Om de test wat meer zin te geven, kunnen we de test uitbreiden zoals hieronder:

_
  Public Sub ConstructorTest()
    Dim name As String = "Nieuwe taak"
    Dim myTask As Task = New Task(name)
    Assert.AreEqual(name, myTask.Name,_
      "Task object niet goed geïnitialiseerd.")
  End Sub

Je ziet dat de controle plaatsvindt met behulp van de Assert.AreEqual()-methode. De Assert-klasse heeft ook een AreEqual()-methode met objecten als parameters en dus zonder generics. De generics-versie heeft echter vaak de voorkeur. Op deze manier wordt namelijk tijdens compilatie al geverifieerd dat de types overeenkomen. Dat scheelt weer enkele veel voorkomende fouten in de test.

De generics-versie heeft echter vaak de voorkeur. Op deze manier wordt namelijk tijdens compilatie al geverifieerd dat de types overeenkomen

We hebben nu alleen nog niet de eigenschap Name opgenomen in de Task-klasse, dus we moeten deze toevoegen. Als we dat niet doen, zou het project niet eens compileren. We hebben nu nog geen implementatie ingevoerd, maar laten we toch eens een test uitvoeren.

Stap 3: Testen uitvoeren

Om alle testen in het project te testen hoeven we enkel het testproject uit te voeren. In Visual Studio selecteer je hiervoor het project TaskOrganizerTest in de solution explorer. In het context-menu kies je Set as StartUp Project. Via F5 of Ctrl-F5 (of Debug > Start Debugging respectievelijk Debug > Start Without Debugging) kun je de testen uitvoeren.

Fig. 4: Het testresultaat na het uitvoeren van de test

In het Test Results-scherm verschijnt een lijst met alle testen in het project. Nu hebben we nog maar één test in het project zitten, dus verschijnt er ook één test met het bijbehorende resultaat. Zodra de uitvoering gestart is, zullen de testen de status pending hebben. Het resultaat van de test is natuurlijk Failed (zie figuur 4). Door op de kolommen in het scherm te klikken kan extra informatie getoond worden. Je kunt ook meer details te weten komen door te dubbelklikken op een regel in het scherm. Via het context-menu kan je per regel direct naar de betreffende programmacode van de test springen.

Nu weten we natuurlijk wat er misgaat in deze test. Je hoeft enkel maar de waarde van de Name-eigenschap opgeven in de constructor aan de hand van de opgegeven parameter. Voeg deze initialisatie toe en voer de test nog eens uit om te controleren dat het nu wel goed gaat.

We hebben nu een begin gemaakt en het project voorzien van unit testen. Door eerst een test te schrijven en daarna de implementatie beschikken we op termijn over een flinke set testen die op ieder moment uitgevoerd kunnen worden. Laten we eens kijken wat er nog meer mogelijk is in een unit test.

Controleren op excepties

De volgende stap in de Task-klasse is een controle op de naam van de taak. De Name-eigenschap kunnen we wel rechtstreeks zetten, maar voordat we deze vanuit de constructor in de eigenschap plaatsen, kunnen we controleren of er wel een valide naam aan de taak wordt toegekend. Hiertoe voegen we twee testen toe die controleren of de opgegeven naam niet null of een lege string is. Hieronder staat de relevante programmacode.

_
    "Ten onrechte wordt Nothing geaccepteerd _
    bij instantiatie.")> _
  Public Sub TestGeenNothingAlsNaam()
    Dim myTask As Task = New Task(Nothing)
  End Sub

_
    "Ten onrechte wordt een lege string geaccepteerd _
    bij instantiatie.")> _
  Public Sub TestGeenLegeStringAlsNaam()
    Dim myTask As Task = New Task("")
  End Sub

Het valt direct op dat er geen try-catch blok nodig is die expliciet test op de betreffende exceptie. Daarentegen is een extra attribuut op de methode geplaatst die het type exceptie als parameter meekrijgt.  Bovendien kan, optioneel, een bericht worden opgegeven zodra de betreffende exceptie niet optreedt. Zodra de test wordt uitgevoerd zal deze falen wanneer de methode geen exceptie opwerpt. Als je de test nu uitvoert (via F5, of Ctrl-F5) zul je merken dat we de parameter in de constructor nog niet valideren, en de test zal dus mislukken.

Op grond van deze falende testen moeten we de programmacode aanpassen zodat we de betreffende functionaliteit wel succesvol kunnen testen. We verifiëren dus eerst de parameter voor we deze toekennen aan de Name-eigenschap.

Private m_name As String
Public Property Name() As String
  Get
    Return m_name
  End Get
  Private Set(ByVal value As String)
    If value Is Nothing Then Throw New _
      ArgumentNullException( _
        "Naam kan niet Nothing zijn.")
    If value.Trim.Length = 0 Then Throw New _
      ArgumentException("Naam kan niet leeg zijn.")
    m_name = value
  End Set
End Property

Public Sub New(ByVal taskName As String)
  Name = taskName
End Sub

We maken in de implementatie van de Name-eigenschap ook gebruik van de mogelijkheid om verschillen in toegankelijkheid toe te passen. Door de Set-methode als Private te markeren kan Name wel geraadpleegd worden buiten de klasse, maar niet veranderd.

Zodra deze validatie is toegevoegd kunnen we de test opnieuw uitvoeren en verifiëren dat de implementatie correct is. Alle drie de testen in het project worden uitgevoerd om te controleren dat er door het toevoegen van deze code geen onverwachte fouten optreden. De echte waarde van unit testen komt tot uiting wanneer de programmacode in de loop der tijd verandert. Een complete reeks van testen zorgt er voor dat we geen functionaliteit stuk maken tijdens het onderhoud en verbetering van deze programmacode.

Een complete reeks van testen zorgt er voor dat we geen functionaliteit stuk maken tijdens het onderhoud en verbetering van deze programmacode

Testgegevens uit een database ophalen

We voegen nu de mogelijkheid toe dat een Task-object ook de voortgang kan bijhouden. Dit gebeurt via een methode met een percentage als parameter. We voegen bovendien een controle toe dat de opgegeven waarde niet groter dan 100 kan zijn. Bovendien geldt dat een taak met een voortgangspercentage tussen 0 en 100 niet klaar kan zijn. Is de voortgang 0 dan is de taak niet gestart, en is staat de teller op 100 dan is de taak gereed.

We moeten, om dit netjes volgens de TDD-methode te doen, eerst een test maken voor de controle op de ingevoerde waarde voordat we de methode implementeren. We moeten echter ook een reeks test-waarden creëren tegen welke we de implementatie kunnen verifiëren. In plaats van een individuele test voor iedere test-case of een for-lus kunnen we ook een data-gedreven test maken die de testgegevens uit een database haalt.

We beginnen met het toevoegen van een test met de naam UpdateProgressTest(). Dit is een methode in de TaskTest-klasse met het attribuut TestMethod(). Via Test > Windows > Test View krijgen we deze test ook te zien in een lijst.

Fig. 5: Test View scherm

Het Test View-scherm kun je gebruiken om specifieke tests uit te voeren en specifieke eigenschappen van een test te bekijken. We kunnen ook extra kolommen toevoegen, via de rechtermuisknop op een kolom. Daarmee kunnen we de testen sorteren en bekijken zoals we zelf willen. Sommige eigenschappen in deze kolommen zijn weer terug te vinden in attributen op de testmethode. Wanneer we bijvoorbeeld via de eigenschappen een test-eigenaar (Owner) hebben opgegeven, zien we deze ook als attribuut Owner("Sander")> terug boven de methode. Er is een vrije-veld attribuut TestProperty waarin een naam-waarde-paar voor van alles kan worden opgeslagen.

We kunnen ook kijken naar eigenschappen die niet in kolommen zijn terug te vinden. Kies hiervoor Properties uit het context-menu. Zo kunnen we onder meer een ConnectionString opgeven en een tabelnaam om testgegevens uit op te halen. Het ligt nogal voor de hand dat wanneer we specifieke testwaarden willen opgeven, we een databaseverbinding nodig hebben. Vanuit de Server Explorer kunnen we via Create new SQL Server Database een database toevoegen aan het testproject. Realiseer je dan wel dat wanneer je deze test op een andere computer wil uitvoeren, de database wel toegankelijk moet zijn. Je kunt daarom ook een database-bestand toevoegen via: Project > Add new item > SQL Database. Daarmee volgen de testgegevens het testproject. Als de database groot wordt is dat natuurlijk minder praktisch en kunnen we beter voor een centrale databaselocatie kiezen. Voor nu voegen we een database bestand toe onder de naam TasksTest.mdf.

Kies daarna Tools > Connect to database…. Selecteer in het dialoogvenster de optie Microsoft SQL Server Database File en kies Continue. Selecteer vervolgens het databasebestand TasksTest.mdf en kies OK. Vanuit de Server Explorer kunnen we nu een tabel met de naam TasksTestData toevoegen. De tabeldefinitie staat in figuur 6.

Fig. 6: Tabeldefinitie voor TasksTestData

Zodra de tabel bewaard is kunnen we gegevens invoeren. Open de tabel (rechtermuisknop op de tabel en dan Show Table Data) en voer de volgende waarden in:

Fig. 7: Testwaarden voor het testen van voortgang

Nu we gegevens in de tabel hebben, moeten we deze koppelen aan de test UpdateProgressTest(). Vanuit het eigenschappen-venster van UpdateProgressTest() vul je de Data Connection String-eigenschap en de Data Table Name-eigenschap. De complete test ziet er als volgt uit:

  "…[complete connectiestring]…", _
  "TasksTestData", _
  DataAccessMethod.Sequential)> _
    _
  Public Sub UpdateProgressTest()
    Dim myException As Exception = Nothing
    Dim taskName As String = _
      TestContext.DataRow("Name").ToString()
    Dim progress As Integer = _
      Convert.ToInt32(TestContext.DataRow("Progress"))
    Dim myTask As Task = New Task(taskName)
    Try
      myTask.UpdateProgress(progress)
    Catch ex As Exception
      myException = ex
    End Try

    If Not myException Is Nothing Then
      Assert.AreNotEqual(GetType(ArgumentException), _
        "Deze exceptie was niet verwacht.")
    Else
      If progress = 0 Then _
        Assert.AreEqual(myTask.Status, _
          TaskStatus.NotStarted)
      If progress > 0 And progress < 100 Then _
        Assert.AreEqual(myTask.Status, _
          TaskStatus.InProgress)
      If progress = 100 Then _
        Assert.AreEqual(myTask.Status, _
          TaskStatus.Finished)
      End If
  End Sub

Het eerst dat opvalt is de toevoeging van het attribuut DataSource waarin de connectiestring, de tabelnaam en de volgorde zijn vastgelegd. Daarnaast zijn de TextContext.DataRow instructies van belang. TestContext is een object dat gegenereerd is via de Create Tests wizard. Dit object wordt automatisch geïnstantieerd tijdens de uitvoering van de test zodat we gerelateerde data kunnen benaderen (zie figuur 8).

Fig. 8: De TestContext klasse als eigenschap van TaskTest

Het TestContext-object biedt gegevens zoals de TestDirectory en TestName met methoden als BeginTimer() en EndTimer(). Voor de test UpdateProgressTest is de DataRow-eigenschap van belang. Omdat UpdateProgressTest het attribuut DataSource kent, zal de methode voor iedere regel in de tabel, ook opgegeven in DataSource, worden aangeroepen. Zo kan programmacode getest worden voor een reeks gegevens. Met zes records in de tabel wordt de test dus 6 keer uitgevoerd.

Het is op deze manier dus erg makkelijk om extra testcases toe te voegen. We hoeven enkel maar testwaarden op te geven in de tabel. We kunnen ook twee tabellen hanteren. Eentje met correcte waarden en eentje zonder, maar in een geïntegreerde test kan met een beetje extra werk getest worden op beide soorten gegevens.

Nu we de test gemaakt hebben, is het zaak de implementatie te schrijven. Eerst voegen we aan het project een enumeratie toe voor de verschillende mogelijkheden van de TaskStatus.

Public Enum TaskStatus
  NotStarted
  InProgress
  Finished
End Enum

Daarna schrijven we de UpdateProgress-methode, als onderdeel van de Task-klasse.

Public Sub UpdateProgress(ByVal progress As Integer)
  If progress > 100 Or progress < 0 Then _
    Throw (New ArgumentNullException( _
      "Waarde moet tussen 0 en 100 zijn."))
  Select Case progress
    Case 0
      m_status = TaskStatus.NotStarted
    Case 100
      m_status = TaskStatus.Finished
    Case Else
      m_status = TaskStatus.InProgress
  End Select
  m_progress = progress
End Sub

Code coverage

Het is belangrijk om vast te stellen hoeveel van de programmacode getest is. Dit kunnen we doen aan de hand van zogeheten code coverage. Standaard staat de code coverage-analyse niet aan. Via Test > Edit Test Run Configurations > Local Test Run kunnen we dit aanzetten in het tabblad Code Coverage. De analyse vindt alleen plaats op de geselecteerde assemblies en ook alleen als de uitvoering van de test zonder debugging plaatst vindt (dus Ctrl-F5 of Debug > Start Without Debugging). Na het uitvoeren van de test kan via Test > Windows > Code Coverage Results bekeken worden hoeveel van de programmacode getest is (zie figuur 9).

Fig. 9: Code Coverage Results

De programmacode zelf is ook gearceerd: groen voor instructies die wel zijn uitgevoerd, rood voor niet geteste instructies. De kleuren kunnen wat afwijken, omdat dit een persoonlijke instelling is.

Op deze manier is eenvoudig te achterhalen of er programmacode in het project zit dat niet volgens de TDD-regels is gemaakt.

Initialisatie en opruimen

Wellicht heb je al vastgesteld dat testen individueel worden uitgevoerd. Het is ook af te raden om testen te maken die verplicht in een bepaalde volgorde moeten worden uitgevoerd. Maar het kan wel zijn dat meerdere testen gebruik maken van een bepaalde database-verbinding of XML Web Service. Het initialiseren van zo’n verbinding kan tamelijk kostbaar zijn, en het is dan niet efficiënt om bij enkele tientallen testen achter elkaar telkens opnieuw een database-verbinding te creëren.

Het is daarom mogelijk om bepaalde methoden te markeren met een attribuut zodat deze methode aan het begin van een testrun worden uitgevoerd. Zo ook natuurlijk aan het eind, met een andere attribuut. Dit zijn respectievelijk de attributen ClassInitialize() en ClassCleanup(). Het is ook mogelijk om iedere test vooraf te laten gaan van een methode en een afsluiting. Hiervoor gebruiken we de attributen TestInitialize() en TestCleanup().

Best Practices

Er zijn verschillende best practices die we kunnen hanteren bij het gebruik van unit testen. Test-driven development is een inmiddels niet meer weg te denken ontwikkelmethodiek. Voor Visual Basic programmeurs is het onderscheid tussen RAD en TDD niet altijd even makkelijk te maken. Bij RAD begint men eerst met het maken van enkele schermen, zetten er buttons, lijsten, labels en invoervelden op. Vervolgens begint de implementatie. Het scherm lijkt wel de unit test. Er zijn echter wel grote verschillen:

  • unit testen richten zich meestal op de business-logica in een project;
  • een test kan op ieder moment en geheel geautomatiseerd worden uitgevoerd;
  • het testresultaat is ondubbelzinnig en er kan makkelijk over gerapporteerd worden.

Het invoeren van unit testen in een ontwikkeltraject kost in het begin wat extra discipline, maar na verloop van tijd gaat het vanzelf en kun je eigenlijk niet meer zonder

Het invoeren van unit testen in een ontwikkeltraject kost in het begin wat extra discipline, maar na verloop van tijd gaat het vanzelf en kun je eigenlijk niet meer zonder. Voor de testen zelf gelden nog wat aanbevelingen en richtlijnen:

  • Zorg er voor dat er geen afhankelijkheden, al dan niet ten aanzien van de volgorde, zijn tussen de testen. Iedere test moet op zichzelf uitgevoerd kunnen worden;
  • Schrijf eerst testen voor het implementeren van enige programmacode;
  • Maak een testklasse per klasse in de programmacode. Zodoende is het testproject makkelijk te beheren en hoef je niet telkens een keuze te maken waar de test geplaatst moet worden.
  • Gebruik Visual Studio om het initiële testproject te genereren. Dat scheelt een hoop werk ten opzichte van het handmatig toevoegen en instellen.
  • Vermijd zo mogelijk machineafhankelijke testen, zoals een test die afhankelijk is van een bepaalde folder. Geen “maar het werkt op mijn PC!”. 
  • Stel vast dat alle testen succesvol zijn voor je een nieuwe test toevoegt. Zodra programmacode breekt, is het aan te raden deze direct te herstellen.
  • Probeer zo veel mogelijk testen te maken die automatisch kunnen worden uitgevoerd. Handmatige testen moeten vermeden worden.
  • Een test moet liefst zo snel mogelijk uitvoerbaar zijn. Als een test langzaam is, wordt deze veelal niet vaak uitgevoerd.
  • Zorg ervoor dat een testmethode slechts één onderdeel test. Dat wil zeggen, maak de scope van een test zo klein mogelijk zodat duidelijk is wat er mis is zodra een test faalt.

Conclusies

In het algemeen kan gesteld worden dat de unit test mogelijkheden in Visual Studio Team System uitgebreid zijn, en zelfs nog verder kunnen worden uitgebreid met third party mogelijkheden. Met code coverage hebben een prima blik op de mate waarin de testen werkelijk de geschreven programmacode controleert. Bovendien kan het aantal testen gerelateerd worden aan het aantal fouten of de hoeveelheid programmacode. Op die manier beschikken we over een aardige indicator van de status van een project.

We hebben in dit artikel gekeken naar het doel en het kader van unit testen. Het voorbeeld, met een eenvoudige opzet maar uitgebreid met testen op basis van een database, heeft getoond wat de mogelijkheden zijn. Door vroeg te beginnen unit testen op te nemen in de ontwikkeling van programma’s ontstaat een testset die op langere termijn bijzonder waardevol zal zijn. De integratie van testen in Visual Studio en bijvoorbeeld Team Foundation Server maakt het gebruik ervan eenvoudig en handig.

Meer informatie

  • Test-Driven Development in Microsoft .NET, James Newkirk, Microsoft Press.
  • www.nunit.org
  • www.testdriven.net
  • Testing Methodologies, MSDN, sdn.urlproxy.com/1

Sources

De sources die bij dit artikel horen kunt u downloaden via Gerz_UnitTesting_SRC.zip.

Commentaar van anderen:
ChristianLouboutin op 17-8-2010 om 4:46
Christian Louboutin Shoes, Christian Louboutin, Christian Louboutin Shoes, Wedding Shoes, Wedding Shoes, Louboutin Shoes, Christian Louboutin Discount copies of the mirror, so the angel of the practical activities of customers who activities. Christian Louboutin Evening, Manolo Blahnik Shoes, Christian, Louboutin, Christian Louboutin Sale, Louboutin Sale, Cheap Christian Louboutin Can you from your shoes, you give yourself into chargeless travel and bear your lifetime. Christian Louboutin Boots, Christian Louboutin Pumps, Christian Louboutin Sandals, Christian Louboutin Flats, Christian Louboutin Wedges, Christian Louboutin Sandals Do you agree to accept and hear the cases angled heel shoes forward or abstract, tear, buttons, and destruction, and the ability to reduce greenhouse gas emissions, it is exactly like daydreaming and shoes. Yves Saint Laurent Shoes, Christian Louboutin Boots, Manolo Blahnik Shoes, Yves Saint Laurent Boots, Miu Miu Shoes, Christian Dior Shoes this is an extra brand and shoes. However, you will never accept the amorous Louboutin christians through brand. Christian Louboutin Flats, Christian, Herve Leger V Neck Dress, Herve Leger Bandage Dress, Herve Leger Dress, Herve Leger V Neck Dress You can visit in your configuration of the life of their shoes were forgiven a brace, air brief you accept defeat them later anniversary, they are careful bag dust, shoe box that you have to go.
wholesale nike shoes op 25-8-2010 om 9:34
supra shoes nike tn shoes replica hats Vibram FiveFingers Kso Trek
Geef feedback:

CAPTCHA image
Vul de bovenstaande code hieronder in
Verzend Commentaar