Найти - Пользователи
Полная версия: Unittest tearDown and fork
Начало » Python для новичков » Unittest tearDown and fork
1
Cyxapeff
Вынес часть функционала в отдельного демона, переделываю тесты, перед каждым тестом хочу демона стартовать, а после соответственно останавливать.
class BaseTest(TestCase):
def setUp(self):
print 'TEST start'
...
self.daemon = MyDaemon('/tmp/daemon-test.pid')
self.daemon.start()

def tearDown(self):
print 'TEST stop'
self.daemon.stop()
Проблема в том, что с появлением daemon.start() метод tearDown() перестаёт вызывается по окончанию теста.

MyDaemon() это http://gist.github.com/613926 (найденный на просторах интернета) с переопределённым методом run.

Погуглил - ничего не нашёл, видимо поисковый запрос составил как-то не так. Не знаю в какую сторону копать, подскажите, пожалуйста.
Александр Кошелев
А тесты выполняются!?:-)
Cyxapeff
Да, первый тест отрабатывает как следует, а дальше естественно ошибка т.к демон уже запущен и pid существует. Если оставить только один тест, то тестирование завершается успешно, консоль возвращается, но tearDown так и не выполняется.
ziro
Я обычно выполняю тесты демонов так

from subprocess import Popen, PIPE

class LaunchResult(object):
'''
Small helper to hold result for daemon launch.


:param output: data from stdout stream;
:param errors: data from stderr stream;
'''
def __init__(self, output, errors):
self.output = output
self.errors = errors

@property
def has_errors(self):
'''
Is was error when daemon executed
'''
return self.errors != ''

class Launcher(object):
'''
Utility class for launching daemon via :mod:`subprocess.Popen`

:param settings: python path for module with settings to owerride defaults;
'''
def __init__(self, settings):
self.settings = settings

def launch(self, command, mode, *opts, **optpairs):
'''
Launch daemon script command

:param command: daemon command to launch;
:param mode: daemon mode for launching command;
:param opts: flag options for command;
:param optpairs: value options for command;
'''
args = ['daemon']

if command: args.append(command)

# Simple option
for option in opts:
if option.startswith('-'):
args.append(option)
else:
args.append('--%s' % option)

# Pair option
for option, value in optpairs.iteritems():
args.append('--%s=%s' % (option, value))

if self.settings:
args.append('--settings=%s' % self.settings)

if mode: args.append(mode)

data = Popen(args, stdout=PIPE, stderr=PIPE).communicate()
return LaunchResult(*data)
То есть тестирую демон как внешний черный ящик. При необходимости записываю команды старта/останова демона в setUp, tearDown
Cyxapeff
Ну примерно так я и поступил сразу. Только через call_command, т.к. тестируется django приложение. Но всё-таки интересно, почему оно так странно не работает.
ziro
Ну если Вы действительно запускаете так, как привели в коде, то ничего удивительного, так как в setUp у Вас вызывается метод start, в котором вызывается метод daemonize, который форкает процесс и завершает запускающий процесс, в данном случае - Ваш тест, так что там не только tearDown, там и функция тестирования не успевает выполнятся так, чтобы Вы видели реальный результат (впрочем в отфоркнутом процессе тест выполнятся продолжает, но к сожалению вес вывод идет в /dev/null, как и положено). И как следствие, второй тест тоже не запускается.

Так что единственный способ на мой взгляд тестировать демоны - это запускать их через subprocess.
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB