Ricerca nel sito web

Come scrivere ed eseguire unit test in Python utilizzando PyTest


Quando scrivi codice in Python, è importante assicurarti che funzioni come previsto. Uno dei modi migliori per farlo è utilizzare i test unitari, che ti aiutano a verificare se piccole parti (o unità) del tuo codice funzionano correttamente.

In questo articolo impareremo come scrivere ed eseguire unit test efficaci in Python utilizzando PyTest, uno dei framework di test più popolari per Python.

Cosa sono i test unitari?

I test unitari sono test piccoli e semplici che si concentrano sul controllo di una singola funzione o di una piccola parte di codice. Aiutano a garantire che il codice funzioni come previsto e possa rilevare tempestivamente i bug.

È possibile scrivere unit test per diverse parti del codice, come funzioni, metodi e persino classi. Scrivendo unit test, puoi testare il tuo codice senza eseguire l'intero programma.

Perché utilizzare PyTest?

PyTest è un popolare framework di test per Python che semplifica la scrittura e l'esecuzione dei test.

È semplice da usare e ha molte funzioni utili come:

  • Ti consente di scrivere casi di test semplici e chiari.
  • Fornisce funzionalità avanzate come dispositivi, test parametrizzati e plug-in.
  • Funziona bene con altri strumenti di test e librerie.
  • Genera risultati e report dei test di facile lettura.

Configurazione di PyTest in Linux

Prima di iniziare a scrivere i test, dobbiamo installare PyTest. Se non hai PyTest installato, puoi installarlo utilizzando il gestore pacchetti Python chiamato pip.

pip install pytest

Una volta installato PyTest, sei pronto per iniziare a scrivere i test!

Scrivi il tuo primo test con PyTest

Iniziamo scrivendo una semplice funzione e poi scrivendone un test.

Passaggio 1: scrivere una funzione semplice

Innanzitutto, creiamo una funzione Python che vogliamo testare. Diciamo che abbiamo una funzione che aggiunge due numeri:

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

Questa è una semplice funzione che prende due numeri a e b, li somma insieme e restituisce il risultato.

Passaggio 2: scrivere un test per la funzione

Ora scriviamo un test per la funzione di aggiunta. In PyTest, i test vengono scritti in file separati, in genere denominati test_*.py per facilitare l'identificazione dei file di test.

Crea un nuovo file chiamato test_add.py e scrivi il seguente codice di test:

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

Spiegazione del codice sopra:

  • Importiamo la funzione add dal file add.py.
  • Definiamo una funzione di test chiamata test_add_numbers(). In PyTest, una funzione di test dovrebbe iniziare con la parola test_.
  • All'interno della funzione test, utilizziamo l'istruzione assert per verificare se il risultato della chiamata alla funzione add corrisponde al valore atteso. Se la condizione nell'istruzione assert è True, il test viene superato; in caso contrario, fallisce.

Passaggio 3: eseguire il test

Per eseguire il test, apri il tuo terminale e vai alla directory in cui si trova il tuo file test_add.py, quindi esegui il seguente comando:

pytest

PyTest troverà automaticamente tutti i file di test (quelli che iniziano con test_) ed eseguirà i test al loro interno. Se tutto funziona correttamente, dovresti vedere un output come questo:

Il punto (.) indica che il test è stato superato. Se si verificassero problemi, PyTest mostrerebbe un messaggio di errore.

Scrivere test più avanzati

Ora che sappiamo come scrivere ed eseguire un test di base, esploriamo alcune funzionalità più avanzate di PyTest.

Test per le eccezioni previste

A volte, vuoi verificare se il tuo codice solleva le eccezioni corrette quando qualcosa va storto. Puoi farlo con la funzione pytest.raises().

Diciamo che vogliamo testare una funzione che divide due numeri. Vogliamo sollevare un'eccezione se il secondo numero è zero (per evitare errori di divisione per zero).

Ecco la funzione divide:

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

Ora scriviamo un test per questa funzione che controlla se viene sollevato il ValueError quando proviamo a dividere per zero:

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)

Spiegazione del codice:

  • Abbiamo aggiunto una nuova funzione di test chiamata test_divide_by_zero().
  • All'interno di questa funzione, usiamo pytest.raises(ValueError) per verificare se viene sollevato un ValueError quando chiamiamo la funzione di divisione con zero come secondo argomento.

Esegui nuovamente i test con il comando pytest. Se tutto funziona correttamente, dovresti vedere questo output:

Utilizzo delle apparecchiature per l'installazione e la pulizia

In alcuni casi, potrebbe essere necessario impostare determinate condizioni prima di eseguire i test o eseguire la pulizia una volta eseguiti i test. PyTest fornisce strumenti per gestire questa situazione.

Un dispositivo è una funzione che è possibile utilizzare per impostare o eliminare le condizioni per i test. Le apparecchiature vengono spesso utilizzate per creare oggetti o connettersi ai database necessari per i test.

Ecco un esempio di utilizzo di un dispositivo per impostare una directory temporanea per testare le operazioni sui file:

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)

Spiegazione del codice:

  • Definiamo un dispositivo chiamato temporary_directory che crea una directory temporanea prima del test e la cancella in seguito.
  • La funzione di test test_create_file() utilizza questo dispositivo per creare un file nella directory temporanea e controlla se il file esiste.

Esegui nuovamente i test con il comando pytest. PyTest rileverà e utilizzerà automaticamente l'apparecchiatura.

Parametrizza i tuoi test con Pytest

A volte è necessario eseguire lo stesso test con input diversi. PyTest ti consente di farlo facilmente utilizzando parametrizza.

Diciamo che vogliamo testare la nostra funzione add con diverse coppie di numeri. Invece di scrivere funzioni di test separate per ogni coppia, possiamo usare pytest.mark.parametrize per eseguire lo stesso test con input diversi.

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

Spiegazione del codice:

  • Usiamo il decoratore pytest.mark.parametrize per definire più set di input (a, b e expected ).
  • La funzione test_add_numbers() verrà eseguita una volta per ogni set di input.

Esegui nuovamente i test con il comando pytest, che eseguirà il test quattro volte, una per ogni serie di input.

Conclusione

In questo articolo, abbiamo imparato come scrivere ed eseguire unit test efficaci in Python utilizzando PyTest per individuare tempestivamente i bug e garantire che il codice funzioni come previsto.

PyTest semplifica la scrittura e l'esecuzione di questi test e, con le sue potenti funzionalità, puoi gestire esigenze di test più complesse man mano che cresci nel tuo viaggio con Python.

Articoli correlati: