pytestの実行中に作成された通常の印刷出力を確認するにはどうすればよいですか?


400

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

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


失敗時のみか、それとも常に?

17
-sはテストごとのキャプチャを無効にします
hpk42

3
@delnan -私はいつもそれを見てみたいと思います
デス

回答:


565

-sスイッチは、単位のテストキャプチャを無効にします。


86
-s=--capture=no
2015年

URLが壊れています。多分これが役立つでしょう:docs.pytest.org/en/latest/capture.html
code_dredd

1
これにより、出力がPytest出力とインターリーブされます。おそらく、Pytestが通常どおりに出力をキャプチャし、テストが成功した場合と失敗した場合の両方で表示することをお勧めします。stackoverflow.com/a/59156707/369977を
pR0Ps

51

upvotedコメントへの受け入れ答えジョーが求められます。

コンソールに印刷する方法がある、それはJUnitのレポートに表示されるように出力をキャプチャするには?

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

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

  • ほとんどのpy.test機能は、外部からインポートすることを意図していないプライベート_pytestパッケージの背後でロックされています。何をしているのかを知らずにそうしようとすると、通常、パブリックパッケージは実行時に不明瞭な例外を発生させます。py.testに感謝します。あなたが得た本当に堅牢なアーキテクチャ。pytest
  • あなたが場合でも行うにプライベート猿パッチ方法を見つけ出す_pytest安全な方法でAPIを、あなたはそうする必要が前に公共実行しpytest、外部でパッケージの実行をpy.test命令。これをプラグイン(たとえば、テストスイートの最上位モジュール)で行うことはできませconftest。py.testが遅延してプラグインを動的にインポートするようになるまでに、monkey-patchに使用したいpy.testクラスはすべてインスタンス化されてから長くなり、そのインスタンスにアクセスできなくなります。これは、サルパッチを意味のある形で適用したい場合、外部py.testコマンドを安全に実行できなくなることを意味します。代わりに、そのコマンドの実行をカスタムsetuptoolsでラップする必要がありますtest 次のコマンドを実行します。
    1. モンキーはプライベート_pytestAPIをパッチします。
    2. public pytest.main()関数を呼び出してpy.testコマンドを実行します。

この回答は、py.test -s--capture=nostderrをキャプチャするがstdout をキャプチャしないオプションをサルパッチングします。デフォルトでは、これらのオプションはstderrもstdoutもキャプチャしません。もちろん、これはまったく意味がありません。しかし、すべての素晴らしい旅は、5年間で誰もが忘れる退屈な前編から始まります。

なぜこれを行うのですか?今からお話ししましょう。私のpy.test-drivenテストスイートには、低速の機能テストが含まれています。これらのテストのstdoutを表示することは役に立ち、安心できます。さらに別の長期実行機能テストが何週間も何もしない場合にleycecが到達するのを防ぎますkillall -9 py.test。ただし、これらのテストのstderrを表示すると、py.testがテストの失敗時に例外トレースバックを報告できなくなります。これはまったく役に立ちません。したがって、py.testを強制してstderrをキャプチャしますが stdoutはキャプチャしません

先にtest進む前に、この回答は、py.testを呼び出すカスタムsetuptools コマンドがすでにあることを前提としています。そうでない場合は、py.testの適切に作成されたグッドプラクティスページの「手動統合」サブセクションを参照してください。

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)

このmonkey-patchを有効にするには、次のようにpy.testを実行します。

python setup.py test -a "-s"

stderrではなく stderrがキャプチャされます。気の利いた!

上記のモンキーパッチをTシャツのstdoutとstderrに拡張することは、自由時間のバレルがいっぱいの読者への課題として残されています。


33

テストを実行するときは、-sオプションを使用します。のすべての印刷ステートメントはexampletest.py、テストの実行時にコンソールに印刷されます。

py.test exampletest.py -s

31

pytestのドキュメントによれば、pytestのバージョン3はテストでのキャプチャを一時的に無効にすることができます:

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は、個々のテストからstdoutをキャプチャし、デフォルトで出力するテストの概要とともに、特定の条件でのみそれらを表示します。

追加の要約情報は、「-r」オプションを使用して表示できます。

pytest -rP

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

pytest -rx

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

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


2
これが私が探していた実際の答えです!ありがとうございました。(stdoutが来る有するAFTER試験結果は、所望されるそれらがインターリーブされる場合、印刷された線は、価値を失う。)
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を印刷する方法を知っていますか?(テストに合格した後ではなく)
Alexandre Huat

3

pytest --capture=tee-sys最近追加されました。stdout / errで出力をキャプチャおよび表示できます。


-4

他の答えは機能しません。唯一のキャプチャ出力を確認する方法は、以下のフラグを使用しています:

pytest-すべてを表示する


6
--show-capture=allデフォルト値です。追加しても何の影響もありません。
hoefling
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.