2016-05-26 30 views
9

Il problema:più eccezioni e la copertura del codice quando l'unità di test pitone

Ecco un esempio artificiale del codice in prova:

from datetime import datetime 

def f(s): 
    try: 
     date = s.split(":")[1] 
     return datetime.strptime(date, "%Y%m%d") 
    except (ValueError, IndexError) as e: 
     # some code here 
     raise 

Ecco una serie di test momento ho:

from datetime import datetime 
import unittest 

from test_module import f 

class MyTestCase(unittest.TestCase): 
    def test_valid_date(self): 
     self.assertEqual(f("1:20130101"), datetime(2013, 1, 1)) 

    def test_invalid_date(self): 
     self.assertRaises(ValueError, f, "1:invalid") 

il test passa e, se corro la copertura con la bandiera --branch, vorrei avere la linea 100% e la copertura ramo:

$ coverage run --branch -m unittest test 
.. 
---------------------------------------------------------------------- 
Ran 2 tests in 0.003s 

OK 
$ coverage report 
Name   Stmts Miss Branch BrPart Cover 
-------------------------------------------- 
test_module.py  7  0  0  0 100% 
-------------------------------------------- 
TOTAL    7  0  0  0 100% 

Si noti tuttavia che il test attualmente in esame solo due casi - quando non c'è eccezione generata, e non v'è un'eccezione ValueError sollevato.

La domanda:

Esiste un modo per coverage di segnalare che non ho ancora testato un caso quando IndexError è sollevata?

+0

Si potrebbe avere un diverso eccetto blocco per IndexError. Penso che la copertura conti solo quali linee sono state eseguite. –

risposta

8

Coverage.py può solo misurare quali percorsi di esecuzione (istruzioni o rami) sono stati eseguiti. Non ha modo di rintracciare quali valori sono stati usati, compresi i tipi di eccezione che sono stati sollevati.

come la vedo io, le opzioni sono:

  1. Separare le clausole di eccezione. Nel codice che hai mostrato, le due eccezioni potrebbero essere generate da linee separate comunque, anche se forse nel tuo codice reale non sono così separabili.

  2. Non preoccuparti delle due eccezioni. I test per questo codice considereranno probabilmente un numero di input diversi, progettati per esercitare casi limite diversi. Coverage.py non può aiutarti a distinguere tra tutti, o assicurarti di aver scritto abbastanza casi. Usa altri criteri per decidere di aver scritto abbastanza casi di test.

+0

Ok, grazie mille. Buona fortuna con i tuoi discorsi su PyCon! – alecxe

1

Penso che si possa provare con due eccezioni separate per le due eccezioni. In tal caso, la copertura della linea mostra che non hai testato una condizione.

from datetime import datetime 

def f(s): 
    try: 
     date = s.split(":")[1] 
     return datetime.strptime(date, "%Y%m%d") 
    except ValueError as e: 
     # some code here 
     raise 
    except IndexError as e: 
     # some code 
     raise 

Se non si vuole ripetere il vostro codice, si potrebbe essere in grado di utilizzare una funzione per questo.

+0

Questa è sicuramente un'opzione, ma la mia curiosità ha ancora questa domanda se la copertura (o altro pacchetto) determinerebbe il percorso di esecuzione non testato senza cambiare il codice sotto test. Grazie! – alecxe