Скрыть вывод stderr в модульных тестах
Я пишу несколько модульных тестов некоторого кода, который использует sys.stderr.write для сообщения об ошибках ввода. Это как и должно быть, но это сжимает вывод unit test. Есть ли способ сказать Python не выводить сообщения об ошибках для одиночных команд, à la 2> /dev/null
?
Ответы
Ответ 1
Я предлагаю написать менеджер контекста:
import contextlib
import sys
@contextlib.contextmanager
def nostderr():
savestderr = sys.stderr
class Devnull(object):
def write(self, _): pass
def flush(self): pass
sys.stderr = Devnull()
try:
yield
finally:
sys.stderr = savestderr
Теперь оберните любой фрагмент кода, stderr которого вы хотите подавить в with nostderr():
, и у вас есть локализованное, временное, гарантированное обратимое подавление stderr, которое вы хотите.
Ответ 2
Вы можете создать фиктивный файловый объект, который ничего не сделал с его выходом, и установить stderr на это:
class NullWriter:
def write(self, s):
pass
sys.stderr = NullWriter()
Если вы хотите только стереть stderr в течение определенной продолжительности, вы можете использовать инструкцию with
следующим образом:
class Quieter:
def __enter__(self):
self.old_stderr = sys.stderr
sys.stderr = NullWriter()
def __exit__(self, type, value, traceback):
sys.stderr = self.old_stderr
with Quieter():
# Do stuff; stderr will be suppressed, and it will be restored
# when this block exits
Требуется Python 2.6 или выше, или вы можете использовать его в Python 2.5 с помощью from __future__ import with_statement
.
Ответ 3
class DevNull(object):
def write(self, data): pass
sys.stderr = DevNull()
Чтобы иметь менее постоянное решение, можно было бы найти что-то вроде следующего:
_stderr = None
def quiet():
global _stderr
if _stderr is None:
_stderr = sys.stderr
sys.stderr = DevNull()
def verbose():
global _stderr
if _stderr is not None:
sys.stderr = _stderr
_stderr = None
Названия функций могут быть лучше
Ответ 4
Другая возможность (помимо назначения sys.stderr
) состоит в том, чтобы структурировать ваш код для записи ошибок в предоставленный файл, но по умолчанию этот файл для sys.stderr. Затем вы можете предоставить писатель DevNull во время тестирования.
Если вы хотите переназначить sys.stderr, вы можете использовать Unittest framework для управления им для вас:
class DevNull(object):
def write(self, data):
pass
class MyTestCase(unittest.TestCase):
def setUp(self):
self.old_stderr = sys.stderr
sys.stderr = DevNull()
def tearDown(self):
sys.stderr = self.old_stderr
Таким образом, каждый тест dev-null stderr, но затем восстанавливает его в конце теста.