← Python/Testen
Les 1 van 8
MODULE 10 · 01◷ 25 min

Een test moet een fout kunnen vinden

Na deze les kun je
  • Een concrete verwachting met assert controleren.
  • Een test schrijven die correcte code accepteert en een gewone fout ontdekt.
  • Verwachte waarden uit de afspraak afleiden.

Gisteren klopte je prijsberekening; vandaag heeft iemand vermenigvuldigen door optellen vervangen. Je kunt opnieuw handmatig kijken, maar die controle vergeet je gemakkelijk bij de volgende wijziging. Een test bewaart een concrete afspraak als uitvoerbare code.

Van kijken naar controleren

Een assertie is een controle die moet kloppen om verder te gaan. Met assert actual == expected vergelijk je de ontvangen waarde met de verwachte waarde. Als die vergelijking onwaar is, ontstaat een AssertionError.

Een geslaagde assertie print niets. Daarom roept het eerste voorbeeld de test echt aan en print het pas daarna een korte bevestiging. Alleen de functie definiëren voert haar inhoud nog niet uit.

Een concrete oppervlakteafspraak
def area(width, height):
    return width * height


def test_area():
    assert area(3, 4) == 12


test_area()
print("De oppervlakteafspraak klopt.")
Verwachte uitvoer
De oppervlakteafspraak klopt.

De naam test_area beschrijft de controle voor een mens. Python geeft een gewone functie met die naam nog geen bijzondere uitvoering. In de volgende les laat je een testbibliotheek zulke functies of methoden organiseren.

Drie losse denkstappen

Kies eerst invoer waarvan je de betekenis begrijpt. Bepaal daarna de verwachte uitkomst vanuit de afspraak. Roep tenslotte de echte functie aan en vergelijk beide waarden.

Bij een rechthoek van drie bij vier is de afspraak twaalf vierkante eenheden. De verwachting staat vast vóór je de berekening uitvoert. Je wilt niet eerst het antwoord van de functie bekijken en datzelfde antwoord vervolgens goedkeuren.

Gebruik kleine getallen die je zelf kunt narekenen. Als een test mislukt, wil je kunnen uitleggen welke afspraak is geschonden. Een lange willekeurige lijst is daarvoor niet automatisch beter dan één zorgvuldig gekozen geval.

Een rood resultaat is soms precies goed

Een tegenvoorbeeld is een geval dat laat zien dat een bewering niet altijd klopt. De foutieve oppervlaktefunctie hieronder telt twee zijden op. Met drie en vier levert dat zeven, zodat dezelfde controle de fout ontdekt.

Dezelfde controle ontdekt een gewone fout
def area(width, height):
    return width + height


def test_area():
    assert area(3, 4) == 12, "drie bij vier moet twaalf zijn"


try:
    test_area()
except AssertionError as error:
    print(type(error).__name__ + ": " + str(error))
Verwachte uitvoer
AssertionError: drie bij vier moet twaalf zijn

Dit voorbeeld vangt de assertiefout alleen op om de ontdekking zichtbaar af te drukken. In je eigen test laat je zo'n mislukte assertie doorlopen. Anders lijkt een gebroken afspraak alsnog geslaagd.

Eén groen geval bewijst niet dat een functie overal goed werkt. Twee en twee zijn bijvoorbeeld onhandige afmetingen om optellen van vermenigvuldigen te onderscheiden: beide leveren vier. Denk daarom ook na over een gewone fout die jouw geval werkelijk zou ontmaskeren.

Veelgemaakte fout: het antwoord zichzelf laten nakijken

assert result == result blijft waar, ook als result verkeerd is. Dezelfde foutieve berekening aan beide kanten herhalen helpt evenmin. Een test heeft een onafhankelijke verwachting nodig.

Gebruik assert voor deze ontwikkelcontroles, niet als blijvende invoerbeveiliging van je programma. Python kan asserties bij geoptimaliseerde uitvoering weglaten. Voor invoerfouten blijven de expliciete controles met raise uit module6 geschikt.

Jouw prijsafspraak

De meegeleverde module pricing berekent het totaal als aantal maal prijs per stuk. Beide argumenten zijn hier niet-negatieve gehele getallen; een aantal of prijs van nul geeft dus nul. Je schrijft alleen tests in test_pricing.py en verandert de bibliotheek niet.

Elke test moet de echte pricing.total aanroepen en de uitkomst controleren. We voeren dezelfde test ook tegen gewone verkeerde berekeningen uit. Zo merk je of je controle werkelijk iets ontdekt.

AAN DE SLAG 0/4
1

Vermenigvuldigen controleren

Schrijf test_total. Controleer met assert dat pricing.total(4, 7) de afgesproken 28 geeft.

2

Nul artikelen controleren

Schrijf test_zero_count. Controleer dat pricing.total(0, 7) nul geeft, zodat een fout die minstens één artikel rekent zichtbaar wordt.

3

Een gratis artikel controleren

Schrijf test_zero_price. Controleer dat pricing.total(3, 0) nul geeft en ontdek daarmee een fout die prijs nul door één vervangt.

4

Eén vast antwoord ontmaskeren

Schrijf test_other_totals. Controleer zowel pricing.total(1, 4) als pricing.total(2, 6) met hun eigen verwachte uitkomst.

Onthoud dit

  • Een assertie vergelijkt gedrag met een afzonderlijk bepaalde verwachting.
  • Een test moet correcte code accepteren én een relevante fout kunnen ontdekken.
  • De gekozen invoer bepaalt welke fout zichtbaar wordt.

Hierna gebruik je unittest om meerdere controles samen uit te voeren en hun resultaten te verzamelen.

test_pricing.py
UitvoerPython
›
›_

Hier komt je resultaat.

Voer je code uit en ontdek
wat je hebt gemaakt.

0/4 stappen
EVEN MEEKIJKEN

Bekijk hoe het kan.

Je mag de oplossing bekijken. Deze poging telt dan niet mee als afgeronde les. Met Reset kun je daarna opnieuw zelf oefenen.