2013-09-26 8 views
17

Ho una suite di test che ho caricato utilizzando TestLoader di (dal modulo unittest) Metodo loadTestsFromModule(), vale a dire,Skip prova unittest senza sintassi decoratore

suite = loader.loadTestsFromModule(module) 

Questo mi dà una perfetta ampio elenco di test funziona bene Il mio problema è che l'imbracatura di test con cui sto lavorando a volte ha bisogno di saltare determinati test in base a vari criteri. Quello che voglio fare è qualcosa di simile:

for test in suite: 
    mark the test as 'to-skip' if it meets certain criteria 

Nota che non posso semplicemente rimuovere il test dalla lista dei test perché voglio il unittest test runner per saltare in realtà i test, aggiungerli al saltato conta, e tutto quel jazz.

La documentazione unittest suggests using decorators intorno ai metodi di prova o classi. Dal momento che sto caricando questi test da un modulo e determinando di saltare in base a criteri non contenuti nei test stessi, non posso davvero usare decoratori. C'è un modo per iterare su ogni singolo test e alcuni come contrassegnarlo come un test "to-skip" senza dover accedere direttamente alla classe di test o ai metodi all'interno della classe?

+0

Potresti considerare py.test, che ha un [skipif] (http://pytest.org/latest/skipping.html#marking-a-test-function-to-be-skipped) –

risposta

9

Utilizzando unittest.TestCase.skipTest:

import unittest 

class TestFoo(unittest.TestCase): 
    def setUp(self): print('setup') 
    def tearDown(self): print('teardown') 
    def test_spam(self): pass 
    def test_egg(self): pass 
    def test_ham(self): pass 

if __name__ == '__main__': 
    import sys 
    loader = unittest.loader.defaultTestLoader 
    runner = unittest.TextTestRunner(verbosity=2) 
    suite = loader.loadTestsFromModule(sys.modules['__main__']) 
    for ts in suite: 
     for t in ts: 
      if t.id().endswith('am'): # To skip `test_spam` and `test_ham` 
       setattr(t, 'setUp', lambda: t.skipTest('criteria')) 
    runner.run(suite) 

stampe

test_egg (__main__.TestFoo) ... setup 
teardown 
ok 
test_ham (__main__.TestFoo) ... skipped 'criteria' 
test_spam (__main__.TestFoo) ... skipped 'criteria' 

---------------------------------------------------------------------- 
Ran 3 tests in 0.001s 

OK (skipped=2) 


---------------------------------------------------------------------- 
Ran 3 tests in 0.002s 

OK (skipped=2) 

UPDATE

Aggiornato il codice di patch setUp invece di metodo di prova. Altrimenti, i metodi setUp/tearDown verranno eseguiti per il test da saltare.

NOTA

unittest.TestCase.skipTest (Test di salto) è stato introdotto in Python 2.7, 3.1. Quindi questo metodo funziona solo in Python 2.7+, 3.1+.

1

Alcune osservazioni:

  • Un test è un oggetto richiamabile con un metodo __call__(result)
  • TestCase fornisce un'interfaccia di livello superiore, consentendo metodi di prova di un'eccezione SkipTest saltare stessi
  • Il skip i decoratori fanno esattamente questo
  • I test saltati vengono registrati chiamando il metodo TestResult.addSkip(test, reason).

Quindi è solo bisogno di sostituire i test per-essere-saltati con un test personalizzato che chiama addSkip:

class Skipper(object): 
    def __init__(self, test, reason): 
     self.test = test 
     self.reason = reason 

    def __call__(self, result): 
     result.addSkip(self.test, self.reason) 
6

Questo è un po 'di un hack, ma perché hai solo bisogno di alzare unittest.SkipTest si può camminare attraverso la vostra suite e modificare ogni test per raccogliere per voi invece di eseguire il codice di prova vero e proprio:

import unittest 
from unittest import SkipTest 

class MyTestCase(unittest.TestCase): 
    def test_this_should_skip(self): 
     pass 

    def test_this_should_get_skipped_too(self): 
     pass 

def _skip_test(reason): 
    raise SkipTest(reason) 

if __name__ == '__main__': 
    suite = unittest.TestLoader().loadTestsFromTestCase(MyTestCase) 
    for test in suite: 
     skipped_test_method = lambda: _skip_test("reason") 
     setattr(test, test._testMethodName, skipped_test_method) 
    unittest.TextTestRunner(verbosity=2).run(suite) 

Quando eseguo questo, questo è l'uscita ottengo:

test_this_should_get_skipped_too (__main__.MyTestCase) ... skipped 'reason' 
test_this_should_skip (__main__.MyTestCase) ... skipped 'reason' 

---------------------------------------------------------------------- 
Ran 2 tests in 0.000s 

OK (skipped=2) 
+0

'test_method' è non usato; 'test_method = getattr (test, test._testMethodName)' sembra non necessario. – falsetru

+0

Hai ragione - rimosso. – girasquid

+1

'raise unittest.SkipTest (ragione)' era esattamente quello che stavo cercando! – oliverpool

1

Google mi ha portato qui.

Ho trovato che il modo più semplice per farlo è sollevare un'eccezione SkipTest quando vengono soddisfatti i criteri di salto.

from unittest.case import SkipTest 

def test_this_foo(self): 
    if <skip conditsion>: 
     raise SkipTest 

E quel test verrà contrassegnato come saltato.