Wow. Ho scoperto stasera che i test delle unità Python scritti usando il modulo unittest
non giocano bene con l'analisi della copertura sotto il modulo trace
. Ecco la più semplice test di unità possibile, in foobar.py
:unittest.py non funziona bene con trace.py - perché?
import unittest
class Tester(unittest.TestCase):
def test_true(self):
self.assertTrue(True)
if __name__ == "__main__":
unittest.main()
Se corro questo con python foobar.py
, ottengo questo output:
.
----------------------------------------------------------------------
Ran 1 test in 0.000s
OK
Grande. Ora voglio eseguire test di copertura e, quindi corro di nuovo con python -m trace --count -C . foobar.py
, ma ora ottengo questo:
----------------------------------------------------------------------
Ran 0 tests in 0.000s
OK
No, Python, non è OK - non è stato eseguito il test! Sembra che l'esecuzione nel contesto di trace
in qualche modo aumenti il meccanismo di rilevamento del test unittest
. Ecco la soluzione (folle) mi si avvicinò con:
import unittest
class Tester(unittest.TestCase):
def test_true(self):
self.assertTrue(True)
class Insane(object):
pass
if __name__ == "__main__":
module = Insane()
for k, v in locals().items():
setattr(module, k, v)
unittest.main(module)
Questo è fondamentalmente una soluzione che reifica il, nome innominabile astratta del modulo di livello superiore fingendo una copia di esso. Posso quindi passare quel nome a unittest.main()
in modo da eludere l'effetto su di esso con lo trace
. Non c'è bisogno di mostrarti l'output; sembra proprio come l'esempio di successo sopra.
Così, ho due domande:
cosa sta succedendo qui? Perché lo
trace
rovina le cose perunittest
?C'è un modo più semplice e/o meno folle per aggirare questo problema?
Ottima spiegazione, grazie. Devo solo dire al modulo di test il suo nome (file) e funziona come un incantesimo, sia da solo che sotto trace.py. –
BTW: provare ad usare cProfile e unittest con 'python -m cProfile [some_test_file.py]' ha lo stesso problema, e la stessa soluzione: 'unittest.main (module = 'tests')'. I motori di ricerca non hanno trovato nulla di specifico per cProfile, quindi aggiungendo un commento per cercare di aiutare la ricerca. –