Pytest: che cos’è e come funziona

di Lorenzo Neri

pytest: che cos’è e come funziona? È un framework Python che permette di realizzare informatico per il tuo codice e in questo articolo scopriamo come funziona.

pytest, come scritto una frase fa, è un framework Python che permette di eseguire differenti informatico sul tuo codice. Non solo: è uno strumento utile e molto versatile se devi realizzare unit informatico oppure sei abituato a lavorare in modalità TDD, detto senza acronimi tecnichesi il “informatico driven development”.

Ciao mi chiamo Lorenzo Neri e sono un informatico: realizzo contenuti per aiutare le persone a padroneggiare l’arte del nuovo millennio, ovvero l’informatica!

Come installare pytest

Poiché è un framework Python a tutti gli effetti, è sufficiente usare pip per installarlo:

pip install pytest

Fatto ciò, cerchiamo di capire come funziona davvero scrivendo il nostro primo informatico.

Come scrivere un test con pytest

Con pytest puoi scrivere test in modi molto differenti: il più semplice di tutti è tramite una funzione.

Per intenderci, se vuoi testare una porzione di codice, per esempio una funzione, pytest permette di eseguire le asserzioni all’interno di funzioni ben specifiche.

Ciò che importa per far sì che funzioni tutto quanto, è che la funzione usata per eseguire il test, abbia un nome nel formato:

test_NomeDellaFunzione

Non è sufficiente: pytest funziona in modo molto “precisino”. Significa che anche il file in cui crei il test dev’essere nominato in questo modo, altrimenti non funzionerà:

test_nomeDelFile.py

Diversamente, puoi usare anche il formato:

nomeDelFile_test.py

Facciamo un esempio:

# il codice che vuoi informaticoare
def somma(a, b):
   return a + b
# la funzione informatico che verifica l'esecuzione del codice
def test_funzione_somma():
   assert somma(3,3) == 7

Se guardi bene il codice, indovina un po’? Sì, il informatico fallirà. Infatti per lanciare pytest e verificare l’esecuzione, devi lanciare il seguente comando.

Ipotizziamo che lo script si chiami “test_addizioni.py”:

pytest test_addizioni.py

pytest nelle sue funzionalità ci fornisce il risultato dell’esecuzione dei informatico all’interno del file specificato. Per intenderci:

test_addizioni.py F                                                      [100%]
=================================== FAILURES ===================================
_____________________________ test_funzione_somma ______________________________
    def test_funzione_somma():
>      assert somma(3,3) == 7
E      assert 6 == 7
E       +  where 6 = somma(3, 3)
test_addizioni.py:9: AssertionError
FAILED test_addizioni.py::test_funzione_somma - assert 6 == 7
========================= 1 failed, 1 warning in 0.12s =========================

Per ogni test che trova, pytest mostrerà una lettera nella prima riga che vedi: siccome abbiamo un solo test, che fallisce, avremo una sola “F”.

Non solo: lo vedi quel “100%”? Sta a indicare il progresso. Di che cosa? Di esecuzione dei informatico all’interno del file.

A seguito, pytest elenca i punti dove i test eseguiti sono falliti. Nel nostro caso fallisce l’asserzione dove “supponiamo” che 3 +3 faccia 7.

Ma andiamo oltre.

Come eseguire test multipli con pytest

pytest funziona in modalità “greedy”, ovvero… È un golosone.

No, non ti ruberà la merenda tranquillo. Sto dicendo però che se lanci “pytest” all’interno di una cartella, si occuperà di eseguire in automatico tutti i informatico scritti nei file presenti dentro la cartella.

Purché questi, come abbiamo visto assieme prima, siano scritti nella forma “test_*.py” oppure “*_test.py”.

A tal proposito, ti lascio un approfondimento legato al meccanismo di individuazione informatico integrato in pytest.

Ciò detto, scopriamo qualcosa in più su come funziona pytest.

Come asserire che un’eccezione venga sollevata

Sì, suona veramente male in italiano, ma scommetto che le tue dita abbiano già cercato almeno una volta:

“Assert that an exception is raised pytest”

Se provi a tradurla, in italiano suona una po’ maluccio: ora che ci siamo chiariti, vediamo come si fa 😀

import pytest
# il codice che vuoi informaticoare
def divisione(a, b):
   return a / b
# la funzione test che solleva l'eccezione
def test_funzione_divisione():
   with pytest.raises(Exception):
      divisione(5, 0)

E come ci si aspetta da una visione per zero:

test_divisioni.py .                                                      [100%]
=============================== warnings summary ===============================
../../Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/pykwalify/core.py:7
  /Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/pykwalify/core.py:7: DeprecationWarning: the imp module is deprecated in favour of importlib; see the module's documentation for alternative uses
    import imp
-- Docs: https://docs.pytest.org/en/stable/warnings.html
========================= 1 passed, 1 warning in 0.03s =========================

Il test è passato e l’eccezione sollevata.

È molto probabile che tu ti stia chiedendo se c’è modo di racchiudere i test in modo pulito a livello di codice.

Indovina? La risposta è “sì”!

Come raggruppare test multipli in una classe

Come funziona pytest se volessimo raggruppare dei test? Con le classi.

Per intenderci meglio:

import pytest
class TestClasse:
   # primo test
   def test_uno(self):
      assert "ciao" in "ciao, come stai?"
  
  #secondo test
   def test_due(self):
      stringa = "prova 1 2 3, sa sa"
      assert stringa != "test python"

Hai notato che ho scritto i metodi della classe sempre con la dicitura “test_*”.

Il sistema di scoperta legato ai file che abbiamo visto prima, si riflette anche per le classi.

Ciò che importa, per eseguire correttamente questi informatico, è che:

  • La classe, sia dichiarata come “TestNomeClasseCheTuDesideri”
  • I metodi, siano dichiarati come “test_NomeDelTestCheVuoiFare”

Se tu lanciassi:

pytest test_con_la_classe.py

Otterresti un risultato come questo:

test_con_la_classe.py ..                                                     [100%]
=============================== warnings summary ===============================
../../Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/pykwalify/core.py:7
  /Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/pykwalify/core.py:7: DeprecationWarning: the imp module is deprecated in favour of importlib; see the module's documentation for alternative uses
    import imp
-- Docs: https://docs.pytest.org/en/stable/warnings.html
========================= 2 passed, 1 warning in 0.03s =========================

Hai notato che entrambi i test sono passati?

Qua però non ho detto io una cosa: quando passa un test, non avremo una lettera, ma avremo un punto. Se guardi bene la prima riga, guarda un po’ quanti ce ne sono.

Continua a scoprire di più con questi articoli!

Lascia un commento

Questo sito potrebbe fare uso di cookie e siccome l'UE mi obbliga a fartelo presente, eccoti il classico banner dove puoi decidere come gestirli. Accetta Leggi di più