Test Unitari in Python
I test unitari sono un metodo per verificare che le singole unitĂ di codice (come funzioni o classi) funzionino come previsto. In Python, il modulo integrato unittest
fornisce un framework potente e flessibile per scrivere e eseguire test automatizzati. Con i test unitari, puoi individuare bug e problemi prima che il tuo codice venga distribuito, garantendo la qualitĂ e la stabilitĂ del software.
In questo articolo esploreremo come scrivere test unitari, eseguirli e analizzare i risultati, oltre a buone pratiche per il testing.
1. Cos’è un Test Unitario?
Un test unitario è una verifica automatizzata che assicura che una funzione, metodo o classe in un programma Python si comporti come previsto in condizioni controllate. I test unitari:
- Validano piccole unitĂ di funzionalitĂ in modo isolato.
- Forniscono una base solida per il refactoring del codice.
- Riduccono il rischio di introdurre bug quando si aggiungono nuove funzionalitĂ .
2. Il Modulo unittest
Il modulo unittest
è un framework integrato in Python per scrivere e organizzare test. Offre strumenti per creare test, raggrupparli in classi, eseguire i test e verificare i risultati.
Importare il Modulo unittest
import unittest
3. Scrivere un Test Unitario di Base
Vediamo un esempio di come creare un semplice test unitario per una funzione che somma due numeri.
Funzione da Testare
def somma(a, b):
return a + b
Scrivere un Test per la Funzione
Per scrivere un test per la funzione somma()
, creiamo una classe che eredita da unittest.TestCase
e definiamo i metodi di test.
import unittest
from mio_modulo import somma # Importa la funzione da testare
class TestSomma(unittest.TestCase):
def test_somma_positivi(self):
self.assertEqual(somma(2, 3), 5)
def test_somma_negativi(self):
self.assertEqual(somma(-1, -1), -2)
def test_somma_zero(self):
self.assertEqual(somma(0, 0), 0)
# Eseguire i test se il file viene eseguito direttamente
if __name__ == '__main__':
unittest.main()
Spiegazione:
TestSomma
: Una classe che rappresenta il gruppo di test. Eredita daunittest.TestCase
.test_somma_positivi
,test_somma_negativi
,test_somma_zero
: Ogni metodo che inizia contest_
viene eseguito automaticamente daunittest
come un test.self.assertEqual()
: Un metodo per verificare che il risultato della funzione sia uguale al valore atteso.
4. Eseguire i Test
Per eseguire i test, puoi semplicemente eseguire il file Python contenente i test. Se i test passano, vedrai un output simile a questo:
$ python test_mio_modulo.py
...
----------------------------------------------------------------------
Ran 3 tests in 0.001s
OK
Se un test fallisce, l’output mostrerà dettagli sull’errore:
$ python test_mio_modulo.py
F..
======================================================================
FAIL: test_somma_positivi (test_mio_modulo.TestSomma)
----------------------------------------------------------------------
Traceback (most recent call last):
File "test_mio_modulo.py", line 6, in test_somma_positivi
self.assertEqual(somma(2, 3), 6)
AssertionError: 5 != 6
5. Altri Metodi di Verifica
Oltre a assertEqual()
, unittest
fornisce diversi metodi per testare le condizioni.
Metodi Comuni di unittest
assertEqual(a, b)
: Verifica chea
sia uguale ab
.assertNotEqual(a, b)
: Verifica chea
non sia uguale ab
.assertTrue(x)
: Verifica chex
siaTrue
.assertFalse(x)
: Verifica chex
siaFalse
.assertIsNone(x)
: Verifica chex
siaNone
.assertIsInstance(a, b)
: Verifica chea
sia un’istanza dib
.
Esempio di Altri Test
import unittest
def is_pari(n):
return n % 2 == 0
class TestIsPari(unittest.TestCase):
def test_pari(self):
self.assertTrue(is_pari(4))
def test_dispari(self):
self.assertFalse(is_pari(3))
def test_valore_none(self):
self.assertIsNone(None)
if __name__ == '__main__':
unittest.main()
6. Testare Eccezioni
Puoi usare il metodo assertRaises()
per verificare che una determinata eccezione venga sollevata da una funzione.
Esempio di Test di Eccezioni
def dividi(a, b):
if b == 0:
raise ValueError("Divisione per zero non consentita")
return a / b
class TestDividi(unittest.TestCase):
def test_divisione_zero(self):
with self.assertRaises(ValueError):
dividi(10, 0)
if __name__ == '__main__':
unittest.main()
In questo esempio, il test verifica che venga sollevata un’eccezione ValueError
quando si tenta di dividere per zero.
7. Setup e Teardown
In alcuni casi, potresti voler eseguire del codice prima o dopo ogni test, come ad esempio preparare un database o chiudere delle risorse. Puoi usare i metodi setUp()
e tearDown()
per questo scopo.
Esempio di Setup e Teardown
class TestConSetupTeardown(unittest.TestCase):
def setUp(self):
# Codice da eseguire prima di ogni test
self.lista = [1, 2, 3]
def tearDown(self):
# Codice da eseguire dopo ogni test
self.lista = None
def test_aggiunta_elemento(self):
self.lista.append(4)
self.assertEqual(self.lista, [1, 2, 3, 4])
if __name__ == '__main__':
unittest.main()
Spiegazione:
setUp()
: Viene eseguito prima di ogni test. In questo caso, prepara una lista.tearDown()
: Viene eseguito dopo ogni test. In questo esempio, pulisce la lista.
8. Eseguire Test con pytest
Oltre a unittest
, puoi utilizzare il popolare framework pytest
, che offre una sintassi piĂą semplice e funzionalitĂ avanzate per scrivere test. Per usare pytest
, devi prima installarlo:
pip install pytest
Poi puoi scrivere test simili a quelli di unittest
, ma senza la necessitĂ di usare una classe.
Esempio di Test con pytest
def somma(a, b):
return a + b
def test_somma_positivi():
assert somma(2, 3) == 5
def test_somma_negativi():
assert somma(-1, -1) == -2
Per eseguire i test, basta eseguire il comando:
pytest
9. Buone Pratiche per i Test Unitari
- Testare solo una cosa alla volta: Ogni test dovrebbe verificare una singola unitĂ di funzionalitĂ .
- Evitare test complessi: Mantieni i tuoi test semplici e facili da capire.
- Isolare i test: I test unitari non dovrebbero dipendere l’uno dall’altro.
- Eseguire test regolarmente: Esegui i test ogni volta che modifichi il codice, per identificare subito eventuali problemi.
Conclusione
I test unitari sono un elemento fondamentale per garantire la qualitĂ e la stabilitĂ del codice. Python fornisce un framework integrato, unittest
, che permette di creare test in modo semplice ed efficace. Con il giusto approccio e l’uso di strumenti come pytest
, puoi migliorare la manutenibilità e l’affidabilità del tuo software.