631

コードにいくつかの print ステートメントを挿入し、それを実行したときに何が出力されるかを確認したい場合があります。それを「実行」する私の通常の方法は、既存のpytestテストを使用することです。しかし、これらを実行すると、標準出力が表示されないようです (少なくとも、私の IDE である PyCharm 内から)。

pytest の実行中に標準出力を表示する簡単な方法はありますか?

4

12 に答える 12

817

この-sスイッチは、テストごとのキャプチャを無効にします (テストが失敗した場合のみ)。

-sと同等--capture=noです。

于 2013-01-19T12:22:57.527 に答える
175

pytest は、個々のテストから stdout をキャプチャし、特定の条件でのみそれらを表示し、デフォルトで出力するテストの概要も表示します。

「-r」オプションを使用すると、追加の概要情報を表示できます。

pytest -rP

合格したテストのキャプチャされた出力を示します。

pytest -rx

失敗したテストのキャプチャされた出力を示します (デフォルトの動作)。

出力のフォーマットは、-s よりも -r の方がきれいです。

于 2019-12-03T12:03:38.613 に答える
60

承認された回答への賛成コメントで、ジョーは次のように尋ねます。

コンソールに出力し、出力をキャプチャして、junit レポートに表示する方法はありますか?

UNIX では、これは一般にティーイングと呼ばれます。理想的には、キャプチャではなくティーイングが py.test のデフォルトになります。理想的ではありませんが、py.test も既存のサードパーティの py.test プラグイン (...とにかく、私が知っている) もティーイングをサポートしていません

サポートされていないことを行うために py.test にモンキーパッチを適用することは簡単ではありません。なんで?なぜなら:

  • ほとんどの py.test 機能は、外部からのインポートを意図していない_pytestプライベートパッケージの背後でロックされています。自分が何をしているのかを知らずにこれを行おうとすると、通常、パブリックパッケージが実行時にあいまいな例外を発生させます。どうもありがとう、py.test。そこにたどり着いた本当に堅牢なアーキテクチャ。pytest
  • 安全な方法でプライベートAPI にモンキー パッチを適用する方法を理解したとしても、外部コマンドによって実行されるパブリック パッケージを実行する前に、それを行う必要がありますこれをプラグイン (テスト スイートの最上位モジュールなど) で行うことはできません。py.test が遅延してプラグインを動的にインポートするまでに、モンキー パッチを適用したい py.test クラスはインスタンス化されていて、そのインスタンスにアクセスできません。これは、モンキーパッチを有効に適用したい場合、外部コマンドを安全に実行できないことを意味します。代わりに、そのコマンドの実行をカスタム setuptools でラップする必要があります_pytestpytestpy.testconftestpy.testtestコマンド(順番に):
    1. プライベート_pytestAPI に Monkey パッチを適用します。
    2. publicpytest.main()関数を呼び出してpy.testコマンドを実行します。

この回答は、py.test-s--capture=nostderr をキャプチャするオプションにモンキー パッチを適用しますが、 stdoutはキャプチャしません。デフォルトでは、これらのオプションは stderr も stdout もキャプチャしません。もちろん、これはまったくティーイングではありません。しかし、すべての偉大な旅は退屈な前日譚から始まり、5 年後には誰もが忘れてしまいます。

なぜこれを行うのですか?今からお伝えします。私の py.test 駆動型テスト スイートには、遅い機能テストが含まれています。これらのテストの stdout を表示することは、役に立ち、心強いものです。これにより、さらに別の長時間実行される機能テストが何週間も続けて何もできなかったときに、 leycecが手を伸ばすのを防ぐことができます。killall -9 py.testただし、これらのテストの stderr を表示すると、py.test がテストの失敗時に例外トレースバックを報告できなくなります。これはまったく役に立ちません。したがって、標準出力ではなく標準エラー出力をキャプチャするように py.test を強制します。

test先に進む前に、この回答は、 py.test を呼び出すカスタム setuptools コマンドが既にあることを前提としています。そうでない場合は、py.test のよく書かれたGood PracticesページのManual Integrationサブセクションを参照してください。

py.test を呼び出すカスタム setuptoolsコマンドを提供するサードパーティの setuptools プラグインであるpytest-runnerをインストールしないでください。pytest-runner が既にインストールされている場合は、おそらくその pip3 パッケージをアンインストールしてから、上記にリンクされている手動のアプローチを採用する必要があります。test

上で強調表示されている手動統合の指示に従ったと仮定すると、コードベースには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)

このモンキー パッチを有効にするには、次のように py.test を実行します。

python setup.py test -a "-s"

stdout ではなくstderr がキャプチャされるようになりました。気の利いた!

上記のモンキーパッチをティー標準出力と標準エラー出力に拡張することは、バレルいっぱいの自由時間を持つ読者への演習として残されています。

于 2016-06-26T05:58:13.403 に答える
37

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')
于 2017-01-08T13:38:22.430 に答える