Wat is unit testing?

Unit testing is een techniek waarbij individuele stukjes code (units) automatisch getest worden om te controleren of ze correct functioneren. Dit helpt bij het vroegtijdig opsporen van fouten en zorgt voor betrouwbare software.

Casus

Een webshop heeft een methode voor het bereken van de totale prijs van een bestelling. Om te controleren of deze methode werkt zoals verwacht wordt, kan een test wordt bedacht om de totale prijs te checken. In plaats van zelf het systeem te gebruiken en handmatig de waarden in te voeren, kan gebruik gemaakt worden van unit testing om deze test te automatiseren.

Hoe zit unit testing in elkaar?

Een unit test bestaat uit een testmethode die een specifieke methode of klasse controleert. De test vergelijkt de werkelijke output met de verwachte output en geeft een melding als deze afwijken. Unit testen zijn opgebouwd aan de hand van een patroon. Dit patroon is opgebouwd in drie onderdelen:

  • Arrange: In dit gedeelte worden alle waarden en klassen geïnitialiseerd en klaargezet om gebruikt te worden in het volgende onderdeel.
  • Act: In dit gedeelte wordt de daadwerkelijke actie uitgevoerd die getest moet worden (bijvoorbeeld het aanroepen van een methode).
  • Assert: Hier wordt het verwachte resultaat vergeleken met het werkelijke resultaat om te controleren of de test slaagt of faalt.

Codevoorbeeld

using System
using NUnit.Framework;
 
[TestFixture]
public class CalculatorTests {
    [Test]
    public void Sum_AddTwoNumbers_ReturnsSum() {
		//Arrange
        Calculator calc = new Calculator();
        int getal1 = 2;
        int getal2 = 3;
 
		//Act
        int resultaat = calc.Sum(getal1, getal2);
 
		//Assert
        Assert.AreEqual(5, resultaat);
    }
}

In dit codevoorbeeld wordt gebruik gemaakt van NUnit als unit test framework. Dit zal verder in het volgende kopje worden behandeld.

Naamgeving van testen

Om een duidelijk overzicht te geven wat in een unit test getest wordt. Hierbij zijn de volgende onderdelen van belang om te overwegen:

  • Methode naam (Bijvoorbeeld Sum)
  • Testscenario (Bijvoorbeeld AddTwoNumbers)
  • Verwacht resultaat (Bijvoorbeeld ReturnsSum) Deze naamgeving is ook in het codevoorbeeld opgenomen.

Hoe gebruik je unit testing?

Unit testing wordt uitgevoerd met een testframework, zoals NUnit, xUnit of MSTest in C#. Dit framework draait testmethodes en rapporteert of ze slagen of falen. In Visual Studio worden deze drie frameworks aangeboden bij het aanmaken van een testproject.

Verschillen tussen frameworks

  • NUnit: Veelgebruikte en krachtige testframework met uitgebreide assert-functionaliteiten. Ideaal voor projecten die een breed scala aan assert-methodes nodig hebben.
  • xUnit: Modern alternatief met een eenvoudiger ontwerp en betere integratie met ASP.NET Core. Voorkeur voor ontwikkelaars die werken aan moderne applicaties met dependency injection.
  • MSTest: Het officiële testframework van Microsoft, goed geïntegreerd met Visual Studio. Geschikt voor teams die gebruik maken van Microsoft-technologieën en officiële ondersteuning willen.

Waarom de een boven de ander kiezen

  • Kies NUnit als je een krachtig en goed gedocumenteerd framework wilt met veel ingebouwde assert-functionaliteiten.
  • Kies xUnit als je een minimalistisch framework wilt dat goed aansluit op moderne ontwikkelingspatronen zoals dependency injection.
  • Kies MSTest als je een testframework nodig hebt dat naadloos werkt met Microsoft-tools en Visual Studio zonder extra configuratie.

Elk testframe heeft een verschillende manieren om testen aan te maken. Hierbij is het mogelijk om één testcase per test te maken of een test waar meerdere testcases op getest kunnen worden.

Casus

  • Input: a = 2 en b = 3
  • Verwachte output: 5
  • Werkelijke output: 5, dus Test geslaagd!

Mogelijke methode die getest moet worden van de casus

public class Calculator {
    public int Som(int a, int b) {
        return a + b;
    }
}

Mogelijke uitwerking voor NUnit

using System 
using NUnit.Framework 
//Met test cases
 
[TestFixture]
public class CalculatorTests { 
  private readonly Calculator calculator = new Calculator(); 
	[TestCase(1, 2, 3)] 
	[TestCase(0, 0, 0)] 
	[TestCase(-1, 1, 0)] 
	[TestCase(-2, -3, -5)] 
	public void Som_TweeGetallen_GeeftVerwachtResultaat(int a, int b, int verwacht) 
	{ 
		Assert.AreEqual(verwacht, calculator.Som(a, b)); 
	} 
}
 
//Zonder test cases
[TestFixture] 
public class CalculatorTests { 
 	private readonly Calculator calculator = new Calculator(); 
	
	[Test] 
	public void Som_PositieveGetallen_GeeftVerwachtResultaat() 
	{ 
		var resultaat = calculator.Som(1, 2); 
		Assert.AreEqual(3, resultaat); 
	}
	
	[Test] 
	public void Som_NegatieveGetallen_GeeftVerwachtResultaat() 
	{ 
		var resultaat = calculator.Som(-1, -2); Assert.AreEqual(-3, resultaat); 
	}
}

Mogelijke uitwerking voor XUnit

using System
using XUnit
 
//Met InlineData
public class CalculatorTests { 
  private readonly Calculator calculator = new Calculator(); 
  
  [Theory] 
  [InlineData(1, 2, 3)]
  [InlineData(0, 0, 0)] 
  [InlineData(-1, 1, 0)] 
  [InlineData(-2, -3, -5)] 
  public void Som_TweeGetallen_GeeftVerwachtResultaat(int a, int b, int verwacht) 
  { 
  	Assert.Equal(verwacht, calculator.Som(a, b)); 
  } 
}
 
//Zonder InlineData
public class CalculatorTests { 
  private readonly Calculator calculator = new Calculator(); 
  
  [Fact] 
  public void Som_PositieveGetallen_GeeftVerwachtResultaat() 
  { 
  	var resultaat = calculator.Som(1, 2); 
  	Assert.Equal(3, resultaat); 
  } 
  
  [Fact] 
  public void Som_NegatieveGetallen_GeeftVerwachtResultaat() 
  { 
  	var resultaat = calculator.Som(-1, -2); 
  	Assert.Equal(-3, resultaat); 
  }
}

Mogelijke uitwerking voor MSTest

using System
using Microsoft.VisualStudio.TestTools.UnitTesting; 
 
//Met DataRows
[TestClass] 
public class CalculatorTests { 
  private readonly Calculator calculator = new Calculator(); 
  
  [TestMethod] 
  [DataRow(1, 2, 3)] 
  [DataRow(0, 0, 0)] 
  [DataRow(-1, 1, 0)] 
  [DataRow(-2, -3, -5)]
  public void Som_TweeGetallen_GeeftVerwachtResultaat(int a, int b, int verwacht) 
  { 
  	Assert.AreEqual(verwacht, calculator.Som(a, b)); 
  } 
}
 
//Zonder DataRows
[TestClass] 
public class CalculatorTests { 
  private readonly Calculator calculator = new Calculator(); 
  
  [TestMethod] 
  public void Som_PositieveGetallen_GeeftVerwachtResultaat() 
  { 
  	var resultaat = calculator.Som(1, 2); 
  	Assert.AreEqual(3, resultaat); 
  } 
  
  [TestMethod] 
  public void Som_NegatieveGetallen_GeeftVerwachtResultaat() 
  { 
  	var resultaat = calculator.Som(-1, -2); 
  	Assert.AreEqual(-3, resultaat); 
  }
}

Bronnen

NUnit: https://nunit.org/
xUnit: https://xunit.net/
MSTest: https://learn.microsoft.com/en-us/dotnet/core/testing/unit-testing-with-mstest


Volgende stap: Stappen unit testing