Как я могу увидеть нормальный вывод печати, созданный во время запуска Pytest?


401

Иногда я хочу просто вставить некоторые операторы print в мой код и посмотреть, что будет напечатано, когда я это осуществлю. Мой обычный способ «тренироваться» это с помощью существующих тестов pytest. Но когда я запускаю их, я не вижу никакого стандартного вывода (по крайней мере, из PyCharm, моей IDE).

Есть ли простой способ увидеть стандартный вывод во время запуска Pytest?


Только на провал или всегда?

17
-s отключает захват каждого теста
hpk42

3
@delnan - Я бы хотел видеть это всегда
Des

Ответы:


566

-sПереключатель отключает в-тест захвата.


86
-s=--capture=no
варенье

URL не работает. Возможно, это поможет: docs.pytest.org/en/latest/capture.html
code_dredd

1
Это приводит к тому, что выходные данные чередуются с выходными данными Pytest. Вероятно, вам нужно, чтобы Pytest фиксировал выходные данные как обычно и отображал их, когда тесты проходят, а также не проходят. См stackoverflow.com/a/59156707/369977
pR0Ps

51

В upvoted комментарий к общепринятом ответ , Джо спрашивает:

Есть ли способ напечатать на консоль И записать вывод, чтобы он отображался в отчете о Junit?

В UNIX это обычно упоминается как тиинг . В идеале, пи-тест будет использоваться по умолчанию, а не в виде захвата. Не в идеале, ни py.test, ни какой-либо существующий сторонний плагин py.test (... в любом случае, о котором я знаю ) не поддерживают teee - несмотря на то, что Python тривиально поддерживает teeing " из коробки" .

Обезьяны-патчи py.test делать что-либо неподдерживаемое нетривиально. Почему? Потому что:

  • Большинство функций py.test заблокированы частным _pytestпакетом, который не предназначен для внешнего импорта. Попытка сделать это, не зная, что вы делаете, обычно приводит к тому, что публичный pytestпакет вызывает неясные исключения во время выполнения. Большое спасибо, py.test. Действительно надежная архитектура у вас там.
  • Даже если вы делаете понять, как обезьяна-патч частного _pytestAPI безопасным образом, вы должны сделать это прежде , чем запустить публичный pytestзапуск пакета внешней py.testкоманды. Вы не можете сделать это в плагине (например, conftestмодуль верхнего уровня в вашем наборе тестов). К тому времени py.test лениво получает вокруг , чтобы динамически импортировать плагин, любой py.test класс вы хотели обезьяньего патч уже давно был создан экземпляр - и вы не имеете доступа к этому экземпляру. Это подразумевает, что, если вы хотите, чтобы ваш monkey-patch применялся осмысленно, вы больше не можете безопасно запускать внешнюю py.testкоманду. Вместо этого вы должны обернуть выполнение этой команды пользовательскими настройкамиtest подайте команду (по порядку):
    1. Обезьяна-патчи частного _pytestAPI.
    2. Вызывает публичную pytest.main()функцию для запуска py.testкоманды.

Этот ответ monkey-patches py.test's -sи --capture=noопции для захвата stderr, но не stdout. По умолчанию эти параметры не захватывают ни stderr, ни stdout. Конечно, это не совсем так. Но каждое великое путешествие начинается с утомительного приквела, который все забывают через пять лет.

Зачем это делать? Я сейчас скажу вам. Мой набор тестов на основе py.test содержит медленные функциональные тесты. Отображение стандартного вывода этих тестов полезно и обнадеживает, предотвращая достижение leycec,killall -9 py.test когда еще один продолжительный функциональный тест не может что-либо делать в течение нескольких недель подряд. Однако отображение stderr этих тестов не позволяет py.test сообщать о трассировках исключений при неудачных тестах. Что совершенно бесполезно. Следовательно, мы принудительно используем py.test для захвата stderr, но не stdout.

Прежде чем мы перейдем к нему, этот ответ предполагает, что у вас уже есть настраиваемая testкоманда setuptools, вызывающая py.test. Если вы этого не сделаете, см Руководства по интеграции подразделу хорошо написанного py.test в Надлежащей практике страницы.

Вы не устанавливать pytest-бегун , сторонние Setuptools плагин Заказное Setuptools testкоманда также применение py.test. Если pytest-runner уже установлен, вам, вероятно, потребуется удалить этот пакет pip3, а затем применить ручной подход, указанный выше.

Предполагая, что вы следовали инструкциям в Ручной интеграции, выделенным выше, ваша база кода должна теперь содержать PyTest.run_tests()метод. Измените этот метод, чтобы он напоминал:

class PyTest(TestCommand):
             .
             .
             .
    def run_tests(self):
        # Import the public "pytest" package *BEFORE* the private "_pytest"
        # package. While importation order is typically ignorable, imports can
        # technically have side effects. Tragicomically, that is the case here.
        # Importing the public "pytest" package establishes runtime
        # configuration required by submodules of the private "_pytest" package.
        # The former *MUST* always be imported before the latter. Failing to do
        # so raises obtuse exceptions at runtime... which is bad.
        import pytest
        from _pytest.capture import CaptureManager, FDCapture, MultiCapture

        # If the private method to be monkey-patched no longer exists, py.test
        # is either broken or unsupported. In either case, raise an exception.
        if not hasattr(CaptureManager, '_getcapture'):
            from distutils.errors import DistutilsClassError
            raise DistutilsClassError(
                'Class "pytest.capture.CaptureManager" method _getcapture() '
                'not found. The current version of py.test is either '
                'broken (unlikely) or unsupported (likely).'
            )

        # Old method to be monkey-patched.
        _getcapture_old = CaptureManager._getcapture

        # New method applying this monkey-patch. Note the use of:
        #
        # * "out=False", *NOT* capturing stdout.
        # * "err=True", capturing stderr.
        def _getcapture_new(self, method):
            if method == "no":
                return MultiCapture(
                    out=False, err=True, in_=False, Capture=FDCapture)
            else:
                return _getcapture_old(self, method)

        # Replace the old with the new method.
        CaptureManager._getcapture = _getcapture_new

        # Run py.test with all passed arguments.
        errno = pytest.main(self.pytest_args)
        sys.exit(errno)

Чтобы включить этот monkey-patch, запустите py.test следующим образом:

python setup.py test -a "-s"

Stderr, но не stdout, теперь будет захвачен. Острота!

Расширение вышеприведенного патча обезьяны на tedout и stderr оставлено в качестве упражнения для читателя с бочкой свободного времени.


33

При запуске теста используйте -sопцию. Все операторы print in exampletest.pyбудут напечатаны на консоли при запуске теста.

py.test exampletest.py -s

31

Согласно документации pytest , версия 3 pytest может временно отключить захват в тесте:

def test_disabling_capturing(capsys):
    print('this output is captured')
    with capsys.disabled():
        print('output not captured, going directly to sys.stdout')
    print('this output is also captured')

20

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

Дополнительная сводная информация может быть показана с помощью опции '-r':

pytest -rP

показывает захваченный вывод пройденных тестов.

pytest -rx

показывает захваченный вывод неудачных тестов (поведение по умолчанию).

Форматирование вывода красивее с -r, чем с -s.


2
Это фактический ответ, который я искал! Спасибо. (Принимая стандартный вывод ПОСЛЕ того, как результаты теста желательны. Когда они чередуются, напечатанные строки теряют значение.)
bossylobster

18

Попробуйте pytest -s -v test_login.pyбольше информации в консоли.

-v это короткий --verbose

-s означает «отключить все захваты»




1
если вы используете файл pytest.ini, вы можете использовать: addopts = -s -v python_files = test_login.py
timj98

4

Если вы используете PyCharm IDE, вы можете запустить этот отдельный тест или все тесты с помощью панели инструментов «Выполнить». В окне инструмента Выполнить отображаются выходные данные, сгенерированные вашим приложением, и вы можете увидеть все операторы печати в них как часть результатов теста.


Знаете ли вы, как сделать печать PyCharm во время теста? (а не после того, как тест пройден)
Александр Хуат

3

pytest --capture=tee-sysбыл недавно добавлен. Вы можете захватить, а также увидеть результат на stdout / err.


-4

Другие ответы не работают. Только способ увидеть захваченный выход использует следующий флаг:

pytest - показать-захватить все


6
--show-capture=allэто значение по умолчанию. Добавление этого ничего не влияет.
крик
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.