Test Metrics.

Python Code Coverage

Python è uno dei linguaggi di programmazione più popolari attualmente disponibili. Grazie alla sua natura generica, Python trova applicazione in vari casi d’uso nello sviluppo di software che vanno dal semplice scripting ai server web a framework come Django.

Tuttavia, come per altri linguaggi di programmazione, il test rimane uno degli aspetti più importanti dello sviluppo di software in Python.

In questo post, vedremo alcuni strumenti per misurare e scrivere la copertura dei casi di test per il codice Python.

Unittest

La libreria standard Python è precostruita con un modulo chiamato unittest. Ispirato a JUnit e ad altri framework di test unitari dei principali linguaggi di programmazione, unittest è un framework di test che permette di automatizzare i test, impostare il codice condiviso di setup e shutdown per i test e altro ancora.

Una delle caratteristiche importanti di unittest è il test fixture, cioè l’impostazione necessaria per eseguire uno o più test, e qualsiasi azione di pulizia associata. Con fixture test, attività come la creazione di database temporanei o proxy, directory, o l’avvio di un processo server, possono essere gestite in un’unica posizione.

Prendiamo alcuni casi di test di esempio e vediamo come sono implementati usando unittest:

import unittest

class TestStringMethods(unittest.TestCase):

def test_upper(self):
self.assertEqual(‘pippo’.upper(), ‘FOO’)

def test_isupper(self):
self.assertTrue(‘FOO’.isupper())
self.assertFalse(‘Foo’.isupper())

def test_split(self):
s = ‘hello world’
self.assertEqual(s.split(), )
# controlla che s.split fallisca quando il separatore non è una stringa
with self.assertRaises(TypeError):
s.split(2)

if __name__ == ‘__main__’:
unittest.main()

Crea un test case sottoclassando unittest.TestCase. Poi potete definire i singoli test con i metodi. Notate che i nomi dei test case dovrebbero iniziare con la parola test. Questa convenzione di denominazione informa il test runner su quali metodi rappresentano i test.

Il test runner è il componente che orchestra l’esecuzione dei test e fornisce il risultato all’utente. La sua implementazione varia e può usare un’interfaccia grafica, un’interfaccia testuale o restituire un valore speciale per indicare i risultati dell’esecuzione dei test.

Pytest

Pytest è un framework di test Python di terze parti. Mira a fornire una struttura per scrivere i vostri test in modo efficiente, rimuovendo tutte le spese generali per la creazione di test. Pytest è supportato da Python 2.7, 3.4, 3.5, 3.6, Jython, PyPy-2.3 su Unix/Posix e Windows.

Diamo uno sguardo a come iniziare con Pytest.Per prima cosa, scarica l’ultima versione e installala tramite pip:

pip install -U pytest

Puoi controllare la versione installata da:

pytest -version

Ora, prendiamo una funzione di esempio e il relativo test case.

# contenuto di test_sample.py
def func(x):
return x + 1def test_answer():
assert func(3) == 5

La funzione func prende un input x e ritorna un valore x + 1. Nel caso di test, asseriamo se la funzione func prende l’input 3 e restituisce 5. Ci si aspetta che questo caso di test fallisca. Per eseguire il test è sufficiente digitare pytest nella directory che contiene il file test_sample.py.

$ pytest
=========================== sessione di test inizia ============================
platform linux – Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y
rootdir: $REGENDOC_TMPDIR, inifile:
collected 1 itemtest_sample.py F ================================= FAILURES =================================
_______________________________ test_answer ________________________________

def test_answer():
> assert func(3) == 5
E assert 4 == 5
E + dove 4 = func(3)

test_sample.py:5: AssertionError
========================= 1 failed in 0.12 seconds =========================

Coverage.py

Coverage.py è uno dei più popolari strumenti di copertura del codice per Python. Utilizza strumenti di analisi del codice e ganci di tracciamento forniti nella libreria standard Python per misurare la copertura. Funziona sulle principali versioni di CPython, PyPy, Jython e IronPython. Puoi usare Coverage.py sia con unittest che con Pytest.

Puoi scaricare l’ultima versione di Coverage e installarlo manualmente, oppure puoi installarlo con pip come:

$ pip install coverage

Ora esegui il tuo programma con coverage come

$ coverage run my_program.py arg1 arg2

Poi per ottenere i dati di copertura, esegui

$ coverage report -m

Ecco un esempio di dati di copertura in uscita

$ coverage report -m
Name Stmts Miss Cover Missing
——————-
my_program.py 20 4 80% 33-35, 39
my_other_module.py 56 6 89% 17-23
——————-
TOTALE 76 10 87%

Genera rapporto in file html:

$ coverage html

Questo è un esempio di rapporto HTML generato da Coverage.py. Include Module, statements, missing, excluded, branches, partial e coverage.

Pytest-cov

Pytest-cov è un plugin Python per generare rapporti di copertura. Oltre alle funzionalità supportate dal comando coverage, supporta anche i test centralizzati e distribuiti. Supporta anche la copertura dei sottoprocessi.

Una volta che hai scritto i casi di test come richiesto con Pytest, puoi usare Pytest-cov per eseguire tutti i test e riportare la copertura.

Per iniziare, installa Pytest-cov come:

$ pip install pytest-cov

Test centralizzati

I test centralizzati riportano la copertura combinata del processo principale e tutti i suoi sottoprocessi. Puoi eseguire test centralizzati usando,

$ py.test -cov= tests/

Test distribuiti

Installa Pytest-xdist, per il supporto ai sistemi distribuiti:

$ pip install pytest-xdist

I test distribuiti possono essere fatti in due modi, dist impostato su load e each. Quando è impostato su load, viene riportata la copertura combinata di tutti gli slave durante i test distribuiti. Gli slave possono essere distribuiti su qualsiasi numero di host e ogni slave può trovarsi in qualsiasi punto del file system. Ogni slave avrà i suoi sottoprocessi misurati.

Per i test distribuiti in ogni modalità, pytest-cov riporta anche la copertura combinata di tutti gli slave. Dal momento che ogni slave sta eseguendo tutti i test, questo permette di generare un rapporto di copertura combinato per più ambienti

Sommario

In questo post, abbiamo imparato a conoscere vari framework Python per i test unitari e la copertura del codice. Mentre questi framework rendono il processo di test facile, avete ancora bisogno di scrivere i test. Ecco alcune buone pratiche da considerare mentre si scrivono i test unitari.

  • Utilizzare nomi lunghi e descrittivi. Questo spesso evita la necessità di dottrine nei metodi di test.
  • I test dovrebbero essere isolati. Non interagire con un vero database o una rete. Usate un database di test separato che viene abbattuto o che usa oggetti finti.
  • Focalizzatevi su una piccola parte di funzionalità.
  • Dovrebbe essere veloce, ma un test lento è meglio di nessun test.
  • Spesso ha senso avere una classe di test case per una singola classe o modello.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato.