2013-07-09 2 views
2

Dire que j'ai unittest Python suivant:Comment pouvez-vous nettoyer un UnitTest Python lorsque setUpClass échoue?

import unittest 

def Test(unittest.TestCase): 
    @classmethod 
    def setUpClass(cls): 
     # Get some resources 
     ... 

     if error_occurred: 
      assert(False) 

    @classmethod 
    def tearDownClass(cls): 
     # release resources 
     ... 

Si l'appel échoue de setUpClass, le tearDownClass n'est pas appelé si les ressources ne sont jamais libérés. C'est un problème lors d'un test si les ressources sont requises par le test suivant.

Existe-t-il un moyen de nettoyer lorsque l'appel à setUpClass échoue?

+0

Quelque chose est mal dans ce une odeur scénario. Qu'essayez-vous de tester? – fabrizioM

+0

@fabrizioM: Qu'est-ce que tu n'aimes pas? Je cours beaucoup de cas de test qui utilisent des ressources communes. Pour réduire le temps d'exécution du test, je ne veux pas configurer les ressources communes à chaque fois. – sickgemini

+0

voir ma réponse :) – fabrizioM

Répondre

4

vous pouvez mettre un try try dans la méthode setUpClass et appeler directement le tearDown dans l'exception. Exiger des ressources externes pour exécuter votre unittest est une mauvaise pratique. Si ces ressources ne sont pas disponibles et que vous devez tester une partie de votre code pour un bug étrange, vous ne pourrez pas l'exécuter rapidement. Essayez de différencier les tests d'intégration des tests unitaires.

+0

'attraper'? srsly? ;) –

+1

bonne prise: D fixé! – fabrizioM

3

De la même manière que vous protégez les ressources ailleurs. try-except:

def setUpClass(cls): 
    # ... acquire resources 
    try: 
     # ... some call that may fail 
    except SomeError, e: 
     # cleanup here 

nettoyage pourrait être aussi simple que d'appeler cls.tearDownClass() dans votre bloc except. Puis vous pouvez appeler assert(False) ou quelle que soit la méthode que vous préférez quitter le test au début.

2

J'ai tout un tas de fonctions d'aide de test qui prennent une instance de test et utilisent addCleanup pour installer/décomposer proprement les threads, les fichiers temporaires, etc ... J'ai donc besoin de l'API addCleanup pour les projecteurs de classe. Je réimplémentées un peu de unittest fonctionnalité doCleanup pour me aider, et utilisé maquette patcher addCleanup() lors de la configuration de la classe

import unittest 
import logging 
import mock 

LOGGER = logging.getLogger(__name__) 

class ClassCleanupTestCase(unittest.TestCase): 
    _class_cleanups = [] 

    @classmethod 
    def setUpClassWithCleanup(cls): 
     def cleanup_fn(): 
      """Do some cleanup!""" 
     # Do something that requires cleanup 
     cls.addCleanup(cleanup_fn) 

    @classmethod 
    def addCleanupClass(cls, function, *args, **kwargs): 
     cls._class_cleanups.append((function, args, kwargs)) 

    @classmethod 
    def doCleanupsClass(cls): 
     results = [] 
     while cls._class_cleanups: 
      function, args, kwargs = cls._class_cleanups.pop() 
      try: 
       function(*args, **kwargs) 
      except Exceptions: 
       LOGGER.exception('Exception calling class cleanup function') 
       results.append(sys.exc_info()) 

     if results: 
      LOGGER.error('Exception(s) raised during class cleanup, re-raising ' 
         'first exception.') 
      raise results[0] 

    @classmethod 
    def setUpClass(cls): 
     try: 
      with mock.patch.object(cls, 'addCleanup') as cls_addCleanup: 
       cls_addCleanup.side_effect = cls.addCleanupClass 
       cls.setUpClassWithCleanup() 
     except Exception: 
      cls.doCleanupsClass() 
      raise 

    @classmethod 
    def tearDownClass(cls): 
     cls.doCleanupsClass()