Hoe PyTest te gebruiken voor unit testing in Python

Wanneer je code schrijft in Python, is het belangrijk om ervoor te zorgen dat je code werkt zoals verwacht. Een van de beste manieren om dit te doen is door gebruik te maken van unittests, die je helpen te controleren of kleine delen (of eenheden) van je code correct functioneren.

In dit artikel leren we hoe we effectieve unittests kunnen schrijven en uitvoeren in Python met behulp van PyTest, een van de populairste testframeworks voor Python.

Wat zijn Unittests?

Unittests zijn kleine, simpele tests die zich richten op het controleren van een enkele functie of een klein stukje code. Ze helpen ervoor te zorgen dat je code werkt zoals verwacht en kunnen vroegtijdig bugs opsporen.

Unittests kunnen worden geschreven voor verschillende delen van je code, zoals functies, methoden en zelfs klassen. Door unittests te schrijven, kun je je code testen zonder het hele programma uit te voeren.

Waarom PyTest gebruiken?

PyTest is een populair testframework voor Python dat het eenvoudig maakt om tests te schrijven en uit te voeren.

Het is eenvoudig te gebruiken en heeft veel nuttige functies zoals:

  • Het stelt je in staat om simpele en duidelijke testcase te schrijven.
  • Het biedt geavanceerde functies zoals fixtures, geparametriseerde tests en plugins.
  • Het werkt goed samen met andere testtools en bibliotheken.
  • Het genereert gemakkelijk leesbare testresultaten en rapporten.

PyTest instellen in Linux

Voordat we beginnen met het schrijven van tests, moeten we PyTest installeren. Als je PyTest nog niet hebt geïnstalleerd, kun je het installeren met de Python-pakketbeheerder genaamd pip.

pip install pytest

Zodra PyTest is geïnstalleerd, ben je klaar om tests te schrijven!

Je Eerste Test Schrijven met PyTest

Laten we beginnen met het schrijven van een eenvoudige functie en vervolgens een test ervoor schrijven.

Stap 1: Schrijf een Eenvoudige Functie

Eerst maken we een Python-functie die we willen testen. Laten we zeggen dat we een functie hebben die twee getallen optelt:

# add.py
def add(a, b):
    return a + b

Dit is een eenvoudige functie die twee getallen a en b neemt, deze bij elkaar optelt en het resultaat teruggeeft.

Stap 2: Schrijf een Test voor de Functie

Nu gaan we een test schrijven voor de add-functie. In PyTest worden tests geschreven in aparte bestanden, meestal genaamd test_*.py om het gemakkelijk te maken om testbestanden te identificeren.

Maak een nieuw bestand genaamd test_add.py en schrijf de volgende testcode:

# test_add.py
from add import add

def test_add_numbers():
    assert add(2, 3) == 5
    assert add(-1, 1) == 0
    assert add(0, 0) == 0

Uitleg van de bovenstaande code:

  • We importeren de add functie uit het add.py bestand.
  • We definiëren een testfunctie genaamd test_add_numbers(). In PyTest moet een testfunctie beginnen met het woord test_.
  • Binnen de testfunctie gebruiken we de assert verklaring om te controleren of het resultaat van het aanroepen van de add functie overeenkomt met de verwachte waarde. Als de voorwaarde in de assert verklaring True is, slaagt de test; anders faalt deze.

Stap 3: Voer de Test uit

Om de test uit te voeren, open je je terminal en navigeer je naar de map waar je test_add.py bestand zich bevindt en voer dan de volgende opdracht uit:

pytest

PyTest zal automatisch alle testbestanden vinden (de bestanden die beginnen met test_) en de tests daarin uitvoeren. Als alles correct werkt, zou je een uitvoer zoals deze moeten zien:

Verifying Python Code Functionality

De punt (.) geeft aan dat de test is geslaagd. Als er problemen waren, zou PyTest een foutmelding tonen.

Meer Geavanceerde Tests Schrijven

Nu we weten hoe we een basis test moeten schrijven en uitvoeren, laten we enkele meer geavanceerde functies van PyTest verkennen.

Testen op Verwachte Uitzonderingen

Soms wil je testen of je code de juiste uitzonderingen oproept wanneer er iets misgaat. Dit kun je doen met de pytest.raises() functie.

Laten we zeggen dat we een functie willen testen die twee getallen deelt. We willen een uitzondering oproepen als het tweede getal nul is (om deling door nul-fouten te voorkomen).

Hier is de divide functie:

# divide.py
def divide(a, b):
    if b == 0:
        raise ValueError("Cannot divide by zero")
    return a / b

Nu laten we een test schrijven voor deze functie die controleert of de ValueError wordt opgeroepen wanneer we proberen te delen door nul:

# test_divide.py
from divide import divide
import pytest

def test_divide_numbers():
    assert divide(10, 2) == 5
    assert divide(-10, 2) == -5
    assert divide(10, -2) == -5

def test_divide_by_zero():
    with pytest.raises(ValueError):
        divide(10, 0)

Uitleg van de code:

  • We hebben een nieuwe testfunctie toegevoegd genaamd test_divide_by_zero().
  • In deze functie gebruiken we pytest.raises(ValueError) om te controleren of een ValueError wordt opgegooid wanneer we de deel-functie aanroepen met nul als tweede argument.

Voer de tests opnieuw uit met de pytest opdracht. Als alles correct werkt, zou je deze uitvoer moeten zien:

Test Your Code with PyTest

Gebruik van Fixtures voor Setup en Cleanup

In sommige gevallen moet je bepaalde voorwaarden instellen voordat je je tests uitvoert of opruimen nadat de tests zijn voltooid. PyTest biedt fixtures om dit te regelen.

Een fixture is een functie die je kunt gebruiken om voorwaarden voor je tests in te stellen of af te breken. Fixtures worden vaak gebruikt om objecten te maken of verbinding te maken met databases die nodig zijn voor de tests.

Hier is een voorbeeld van het gebruik van een fixture om een tijdelijke directory op te zetten voor het testen van bestandsbewerkingen:

# test_file_operations.py
import pytest
import os

@pytest.fixture
def temporary_directory():
    temp_dir = "temp_dir"
    os.mkdir(temp_dir)
    yield temp_dir  # This is where the test will run
    os.rmdir(temp_dir)  # Cleanup after the test

def test_create_file(temporary_directory):
    file_path = os.path.join(temporary_directory, "test_file.txt")
    with open(file_path, "w") as f:
        f.write("Hello, world!")
    
    assert os.path.exists(file_path)

Uitleg van de code:

  • We definiëren een fixture genaamd temporary_directory die een tijdelijke directory aanmaakt voordat de test begint en deze daarna verwijdert.
  • De testfunctie test_create_file() gebruikt deze fixture om een bestand in de tijdelijke directory te maken en controleert of het bestand bestaat.

Voer de tests opnieuw uit met de pytest-opdracht. PyTest detecteert en gebruikt de fixture automatisch.

Parameteriseer je tests met Pytest

Soms wil je dezelfde test uitvoeren met verschillende invoer. PyTest stelt je in staat dit eenvoudig te doen met parametrize.

Laten we zeggen dat we onze add functie willen testen met verschillende paren getallen. In plaats van aparte testfuncties te schrijven voor elk paar, kunnen we pytest.mark.parametrize gebruiken om dezelfde test met verschillende invoer te draaien.

# test_add.py
import pytest
from add import add

@pytest.mark.parametrize("a, b, expected", [
    (2, 3, 5),
    (-1, 1, 0),
    (0, 0, 0),
    (100, 200, 300)
])
def test_add_numbers(a, b, expected):
    assert add(a, b) == expected

Uitleg van de code:

  • We gebruiken de pytest.mark.parametrize decorator om meerdere sets invoer (a, b en verwacht) te definiëren.
  • De test function test_add_numbers() zal één keer draaien voor elke set invoer.

Draai de tests opnieuw met het pytest-commando, dat de test vier keer zal uitvoeren, één keer voor elke set invoer.

Conclusie

In dit artikel hebben we geleerd hoe we effectieve unittests kunnen schrijven en uitvoeren in Python met behulp van PyTest om fouten vroegtijdig op te sporen en ervoor te zorgen dat je code werkt zoals verwacht.

PyTest maakt het gemakkelijk om deze tests te schrijven en uit te voeren, en met zijn krachtige functies kun je complexere testbehoeften aan als je verdergaat in je Python-reis.

Source:
https://www.tecmint.com/unit-testing-python-code-with-pytest/