Захват прерываний стандартного вывода в pytest

#python #python-2.7 #pytest

#python #python-2.7 #pytest

Вопрос:

Досадно, что кто-то в моей компании написал библиотеку, полную функций, которые записывают данные в стандартный вывод. Мне нужно захватить и использовать эти данные, поэтому я написал это.

 def capture_output(f):
    orig_stdout = sys.stdout
    sys.stdout = StringIO()
    f()
    output = sys.stdout.getvalue()
    sys.stdout.close()
    sys.stdout = orig_stdout
    return output
  

Редактировать: это не для тестирования. Мне нужно вызвать метод, который печатает кучу данных в стандартный вывод и получает эти данные в виде строки (фактически не печатая ее). Это цель capture_output метода. Я не могу использовать capsys , потому что это бизнес-логика, а не тестовая логика.

Вот мой модульный тест для этого.

 def test_capture_output(self):
    output = temp_logger.capture_output(lambda: print('Hello'))
    assert output == 'Hellon'
  

Все хорошо (тест проходит), пока я вызываю pytest следующим образом:

 pytest path/to/test.py
  

но если я назову это так:

 pytest
  

который запускает все наши тесты, мой тест прерывается.

 ______________________________________________________________________________ TestTempLogger.test_capture_output ______________________________________________________________________________

self = <test_temp_logger.TestTempLogger testMethod=test_capture_output>

    def test_capture_output(self):
        output = temp_logger.capture_output(lambda: print('Hello'))
>       assert output == 'Hellon'
E       AssertionError: assert '' == 'Hellon'
E           Hello

ppt/tests/tools/FIOLauncher/dependencies/test_temp_logger.py:35: AssertionError
------------------------------------------------------------------------------------- Captured stdout call -------------------------------------------------------------------------------------
Hello
  

Я предполагаю, что это как-то связано с тем, как pytest фиксирует данные, записанные в стандартный вывод, но я не понимаю, почему он будет вести себя по-разному в зависимости от того, как я его вызываю. Я также не смог найти никакого обходного пути для этого.

Кто-нибудь знает, что здесь происходит?

Я использую pytest 4.6.10 (последнюю версию, к которой у меня есть доступ) и python 2.7.18 (к сожалению).

Комментарии:

1. у pytest есть capsys приспособление, которое уже делает это.

2. «… которые записывают данные в стандартный вывод» Ну, это цель стандартного вывода.

3. @wim 1, просто используйте приспособление; это то, для чего это нужно, и нет никакой пользы от попыток точно выяснить, как попытка ручного развертывания решения мешает встроенному.

4. Можете ли вы показать, как прерываются тесты? Я предполагаю, что что-то сброшено неправильно, но не знаю, что это такое. Кстати, было бы лучше использовать try/finally в вашей функции, чтобы гарантировать, что stdout всегда восстанавливается. @wim — вопрос заключается в тестировании функции, которая перенаправляет stdout , а не в выполнении этого в тесте.

5. @wim цель capture_stdout не для тестирования. Мне нужно получить вывод функции, которая печатает в стандартный вывод в виде строки как часть моей бизнес-логики. Но у меня есть тест, чтобы убедиться, что он работает, и это то, что ломается.

Ответ №1:

Оказывается, это был другой тест, в котором была эта строка.

 sys.modules['sys'] = MagicMock()
  

вздох

и вот что самое интересное, тесты отлично работают без этого.