2013-07-09 3 views
2

Скажем, у меня есть следующий Python UnitTest:Как вы можете очистить Python UnitTest, когда setUpClass не удается?

import unittest 

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

     if error_occurred: 
      assert(False) 

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

Если вызов setUpClass терпит неудачу, tearDownClass не называется поэтому ресурсы никогда не освобождены. Это проблема во время тестового прогона, если ресурсы необходимы для следующего теста.

Есть ли способ сделать очистку при сбое setUpClass?

+0

Что-то пахнущая плохо в этом сценарии. Что вы пытаетесь проверить? – fabrizioM

+0

@fabrizioM: Что вам не нравится? Я запускаю множество тестовых примеров, которые используют некоторые общие ресурсы. Чтобы сократить время выполнения теста, я не хочу каждый раз настраивать общие ресурсы. – sickgemini

+0

см. Мой ответ :) – fabrizioM

ответ

4

вы можете поместить попытку catch в метод setUpClass и вызвать непосредственно tearDown в исключении.

def setUpClass(cls): 
    try: 
     # setUpClassInner() 
    except Exception, e: 
     cls.tearDownClass() 
     raise # to still mark the test as failed. 

Требование внешних ресурсов для запуска вашего unittest - это плохая практика. Если эти ресурсы недоступны, и вам нужно протестировать часть кода для странной ошибки, вы не сможете ее быстро запустить. Попытайтесь отличить тесты интеграции от Unit Tests.

+0

'catch'? srsly? ;) –

+1

хороший catch: D исправленный! – fabrizioM

3

Точно так же вы защищаете ресурсы в другом месте. try-except:

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

Cleanup может быть столь же просто, как вызов cls.tearDownClass() в вашем except блоке. Затем вы можете позвонить assert(False) или любым другим способом, который вы предпочитаете выходить из теста раньше.

2

У меня есть целая группа тестовых вспомогательных функций, которые берут тестовый экземпляр и используют addCleanup для чистой установки/срыва потоков, файлов temp и т. Д., Поэтому мне понадобился API AddCleanup для работы с инструментами уровня класса. Я переписана немного о UnitTest функциональности doCleanup, чтобы помочь мне, и использовать макет для исправления addCleanup() во время установки класса

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() 
Смежные вопросы