1 2021-11-23: Testing

1.1 Intro

Gegeven een functie kwadraat:

def kwadraat(x):
    return x**2

Kunnen we een test schrijven die controlleert dat de functie ook echt het kwadraat berekent:

1def test_kwadraat_2():
2    # Bereken het kwadraat van 2
3    resultaat = kwadraat(2)
4
5    # Controlleer dat het resultaat 4 is
6    assert resultaat == 4

Op regel 3 gebruiken de te testen function kwadraat. Op regel 6 controlleren we dat de variabele resultaat de waarde bevat die we verwachten.

Merk op, dat als kwadraat als volgt geimplementeerd was, de test ook zou slagen:

def kwadraat(x):
    return 4

Daarom wordt er typisch meer dan 1 test geschreven voor een bepaalde functie:

def test_kwadraat_25():
    resultaat = kwadraat(5)

    assert resultaat == 25

1.2 Kommagetallen

Als het resultaat van een functie een kommagetal is, wordt het gebruik van de gelijkheidsoperator niet aangeraden:

1def invers(x):
2    return 1 / x
3
4
5def test_invers_3():
6    result = invers(3)
7    assert result == 0.333  # Hoeveel drietjes??

We kunnen beter controleren of het resultaat “dicht genoeg” bij de verwachtte waarde ligt. We controleren dus of het verschil tussen het resultaat en de verwachtte waarde kleiner is dan een klein getal. Dit getal bepaalt dus onze precisie (in onderstaande code 0.1).

1def invers(x):
2    return 1 / x
3
4
5def test_inverse_3():
6    result = invers(3)
7    assert abs(result - 0.3) < 0.1

Als we deze precisie voor meerdere testen willen gebruiken, kunnen we deze beter via een globale variabele beschikbaar maken voor alle testen:

 1PRECISIE = 0.1
 2
 3
 4def invers(x):
 5    return 1 / x
 6
 7
 8def test_invers_3():
 9    result = invers(3)
10    assert abs(result - 0.3) < PRECISIE
11
12
13def test_invers_4():
14    result = invers(4)
15    assert abs(result - 0.25) < PRECISIE

1.3 TDD

In de jaren 90 werden testen typisch door een apart team geschreven (QA). Begin jaren 2000 werd het schrijven van (unit)testen door de software-ontwikkelaars zelf populair. Veelal werden de testen geschreven na het schrijven van de ‘echte’ code. Deze testen konden dan aangeven of de code werkte zoals bedoeld was. Vooral bij wijzigingen aan code zijn dit soort testen van onschatbare waarde.

Halfweg jaren 2000 kwam de term Test Driven Development op: Bij dit software development process schrijft de software ontwikkelaar eerst de testen, en vervolgens de echte code.

De stappen zijn als volgt:

  1. schrijf een test

  2. voer de test uit en verifieer dat deze nieuwe test faalt

  3. schrijf de meest eenvoudige code die de test doet slagen

  4. voer alle testen uit en kijk of alle testen nu nog slagen

  5. kuis de nieuwe code op, en voer de testen uit om te controlleren of je code nog correct is

Deze aanpak heeft een aantal belangrijke voordelen:

  • Omdat je in je testen je code “gebruikt”, kijk je meteen naar een handige interface om je code te gebruiken.

  • Je schijft automatisch testen voor je code (als je dit nadien doet, wordt het nogal eens vergeten of uitgesteld om kosten te besparen)

  • Er wordt minder onnodige code geschreven, omdat je enkel de code dient te schrijven die de testen doet slagen.