2015-10-03 9 views
5

Ho usato solo unittest per un breve periodo. Sto usando Jython 2.7.10 "versione finale"Come si usa unittest.TestResult?

Negli Python 2.7 documentazione che spiega TestResult dice:

I seguenti metodi della classe TestResult sono utilizzati per mantenere i strutture dati interne, e possono essere esteso in sottoclassi per supportare requisiti di report aggiuntivi. Ciò è particolarmente utile negli strumenti di costruzione che supportano la segnalazione interattiva mentre i test sono eseguiti .

StartTest (test) ... stopTest (test) ... startTestRun() ... stopTestRun() ¶

Questo è quello che voglio fare ... ma non riesco a capire come usi TestResult. Ecco uno SSCCE ...

import unittest 

class TestResultX(unittest.TestResult): 
    def startTest(self, test): 
     print('# blip') 
     unittest.TestResult.startTest(self, test) 
    def stopTest(self, test): 
     print('# blop') 
     unittest.TestResult.stopTest(self, test) 
    def startTestRun(self): 
     print('# blep') 
     unittest.TestResult.startTestRun(self) 
    def stopTestRun(self): 
     print('# blap') 
     unittest.TestResult.stopTestRun(self) 

class TestCaseX(unittest.TestCase): 
    def test_nonsense(self): 
     print('# wotcha') 
     self.assertTrue(False) 

    def run(self, test_result=None): 
     print('# spoons starting...') 

     test_result = TestResultX() 
     unittest.TestCase.run(self, test_result) 

     print('# ...spoons ended, tr %s' % (test_result, )) 

unittest.main() 

risultati in:

# spoons starting... 

---------------------------------------------------------------------- 
Ran 0 tests in 0.015s 

OK 
# blip 
# wotcha 
# blop 
# ...spoons ended, tr <__main__.TestResultX run=1 errors=0 failures=1> 

Domande:

  • Perché si dicono 0 tests?
  • Perché blep e blap (inizio e fine corsa) non vengono stampati?

Su una nota più generale:

  1. Qualcuno può forse puntare a un buon tutorial/libro che spiega "uso corretto"/"buona pratica" quando si tratta di TestResult, TestRunner, TestLoader, ecc Ho ottenuto "TDD con Python", ma non sembra spiegare nulla di tutto questo.

  2. Qualcuno potrebbe dirmi perché unittest2 sembra essere usato al posto di unittest?

addendum

Dopo gli sforzi di Omar Diab a guardare il codice sorgente Ho provato questo:

def run(self, *args, **kvargs): 
    result = self.defaultTestResult() 
    startTestRun = getattr(result, 'startTestRun', None) 
    logger.info('# calling superclass run... startTestRun? %s' % (startTestRun,)) 
    unittest.TestCase.run(self, *args, **kvargs ) 
    logger.info('# ... superclass run ended') 

Purtroppo ogni metodo test_XXX poi ha dato:

# calling superclass run... startTestRun? <bound method TestResult.startTestRun of <unittest.result.TestResult run=0 errors=0 failures=0>> 

setUp for test_that_stuff_happened (__main__.xx_FT) 

tearDown for test_that_stuff_happened (__main__.xx_FT) 
end tearDown... 
. # ... superclass run ended 
+0

Mi sono imbattuto in questo - devo dire, la documentazione di tutto questo è piuttosto orribile ... –

risposta

0

unittest2 è un backport di nuove funzionalità di unittest per Python 2.4-2.6 It significa che, se si dispone di alcuni script Python 2.4-2.6 e si desidera eseguire in 2.7 e versioni successive, si dovrebbe usare.

potete trovare i dettagli qui: https://docs.python.org/2/library/unittest.html

+1

Grazie per aver spiegato unittest2. Quel collegamento è il documento Python 2.7 da cui ho citato e che non è abbastanza esplicativo. –

1

Wow, non risposte. Sono sorpreso.

Si tratta di un hack, che la maggior parte delle persone potrebbero senza dubbio lavorare per se stessi, se si vuole roba accada all'inizio della corsa e fine della corsa:

sottoclasse TestCase, come da:

def setUp(self): 
    if not hasattr(unittest.TestCase, 'app'): 
     unittest.TestCase.app = MyApp() 
     def shutdown_func(): 
      pass # do any end-of-run stuff here 
     atexit.register(shutdown_func) 
     pass # do any start-of-run stuff here 
    self.app = unittest.TestCase.app 

poi fare tutto il vostro TestCases sottoclasse da questo ...

Il punto è, se si vuole che questo accada, che la vostra applicazione è costruito solo una volta. La responsabilità di garantire che sia "incontaminata" per ogni successiva setUp dipende da te, naturalmente. Ovviamente è possibile utilizzare setUpClass, ma non si ha accesso all'istanza TestCase.

0

Ho lo stesso problema, quindi ho dato un'occhiata al codice sorgente.

Ispezionando unittest.TextTestRunner e unittest.TestCase, sembra che startTestRun() e stopTestRun() vengano richiamati manualmente. In unittest.TextTestRunner, funziona in questo modo:

def run(self, test): 
    # ... 
    startTestRun = getattr(result, 'startTestRun', None) 
    if startTestRun is not None: 
     startTestRun() 
    # ... 

e nel tuo caso, unittest.TestCase, è in questo modo:

def run(self, result=None): 
    orig_result = result 
    if result is None: 
     result = self.defaultTestResult() 
     startTestRun = getattr(result, 'startTestRun', None) 
     if startTestRun is not None: 
      startTestRun() 
    # ... 

così sembra startTestRun solo in realtà viene chiamato da TestCase.run() se non lo fai passare in result. Stai passando result, quindi non sta succedendo.

Questo mi sembra un bug! Ma fondamentalmente significa che puoi estendere TestCase o TestSuite, reimplementare il metodo run e quindi chiamare questi metodi a mano; o semplicemente chiamali al di fuori dei rispettivi metodi run.

Spero che questo aiuti!

+0

Grazie per aver guardato il codice sorgente. Avrei dovuto farlo io, naturalmente! Sfortunatamente il tuo suggerimento di re-engineering del metodo run non ha funzionato per me. Vedi l'addendum che sto facendo al post originale ... –