pytestでコンソールに出力する方法は?


175

でTDD(テスト駆動開発)を使用しようとしていますpytest。 私が使用するときにコンソールにpytestはありません。printprint

私はpytest my_tests.pyそれを実行するために使用しています。

documentationデフォルトで動作するはずだと言っているようです:http : //pytest.org/latest/capture.html

だが:

import myapplication as tum

class TestBlogger:

    @classmethod
    def setup_class(self):
        self.user = "alice"
        self.b = tum.Blogger(self.user)
        print "This should be printed, but it won't be!"

    def test_inherit(self):
        assert issubclass(tum.Blogger, tum.Site)
        links = self.b.get_links(posts)
        print len(links)   # This won't print either.

標準出力コンソールには何も出力されません(通常の進行状況と、合格/不合格となったテストの数だけ)。

そして、私がテストしているスクリプトにはprintが含まれています。

class Blogger(Site):
    get_links(self, posts):
        print len(posts)   # It won't get printed in the test.

ではunittestモジュール、すべては私が必要とする正確に何である、デフォルトで印刷されます。しかし、pytest他の理由で使用したいと思います。

印刷文を表示する方法を知っている人はいますか?


1
stdoutが上書きされている可能性があります。使用するとどうなりますsys.stdout.write("Test")か?いかがsys.__stdout__.write("Test")ですか?後者は、常にシステム定義のstdout(コンソール)に書き込む必要があります。2つのコマンドの動作が異なる場合、stdoutが変更されています。彼らが同じことをするなら、問題は別のものです。
TheSoundDefense 14

回答:


205

デフォルトでpy.testは、標準出力の結果をキャプチャして、印刷方法を制御できるようにします。これを行わなかった場合、どのテストがそのテキストを印刷したかというコンテキストがなければ、多くのテキストが吐き出されます。

ただし、テストが失敗した場合は、結果のレポートに、その特定のテストで標準出力されたものを示すセクションが含まれます。

例えば、

def test_good():
    for i in range(1000):
        print(i)

def test_bad():
    print('this should fail!')
    assert False

結果は次のようになります。

>>> py.test tmp.py
============================= test session starts ==============================
platform darwin -- Python 2.7.6 -- py-1.4.20 -- pytest-2.5.2
plugins: cache, cov, pep8, xdist
collected 2 items

tmp.py .F

=================================== FAILURES ===================================
___________________________________ test_bad ___________________________________

    def test_bad():
        print('this should fail!')
>       assert False
E       assert False

tmp.py:7: AssertionError
------------------------------- Captured stdout --------------------------------
this should fail!
====================== 1 failed, 1 passed in 0.04 seconds ======================

Captured stdoutセクションに注意してください。

print実行されているステートメントを確認したい場合は、-sフラグをに渡すことができますpy.test。ただし、これは解析が難しい場合があることに注意してください。

>>> py.test tmp.py -s
============================= test session starts ==============================
platform darwin -- Python 2.7.6 -- py-1.4.20 -- pytest-2.5.2
plugins: cache, cov, pep8, xdist
collected 2 items

tmp.py 0
1
2
3
... and so on ...
997
998
999
.this should fail!
F

=================================== FAILURES ===================================
___________________________________ test_bad ___________________________________

    def test_bad():
        print('this should fail!')
>       assert False
E       assert False

tmp.py:7: AssertionError
====================== 1 failed, 1 passed in 0.02 seconds ======================

2
非常に実用的です。よくやった!
cmc

1
hmm ...まだ私の印刷ステートメントを記録しません
Tim Boland

67

-sオプションを使用すると、すべての関数の出力が印刷されますが、多すぎる場合があります。

特定の出力が必要な場合は、言及したドキュメントページにいくつかの提案があります。

  1. assert False, "dumb assert to make PyTest print my stuff"関数の最後に挿入すると、テストの失敗による出力が表示されます。

  2. PyTestから渡された特別なオブジェクトがあり、出力をファイルに書き込んで後で検査できます。

    def test_good1(capsys):
        for i in range(5):
            print i
        out, err = capsys.readouterr()
        open("err.txt", "w").write(err)
        open("out.txt", "w").write(out)

    outおよびerrファイルを別のタブで開いて、エディターに自動的に更新させるか、簡単なpy.test; cat out.txtシェルコマンドを実行してテストを実行できます。

それはかなりハッキーな方法ですが、それが必要なものかもしれません:結局のところ、TDDは、ものをいじって、準備ができたらそれをクリーンでサイレントのままにすることを意味します:-)。


pytest 3.8.1でバージョン1を試してみましたが、残念ながらテスト関数ブロックのみが印刷されますが、printステートメントからの出力は印刷されません:(これ以上のトリックはありませんか?
UV

@UV- print()関数を使用する代わりに、出力する変数またはメッセージをアサートステートメントのカンマの後に置く必要があります 。たとえば、pytestレポートのassert False, what_are_you値を「出力」しますwhat_are_you
Mart Van de Ven

43

短い答え

次の-sオプションを使用します。

pytest -s

詳細な回答

ドキュメントから:

テストの実行中に、stdoutおよびstderrに送信されたすべての出力がキャプチャされます。テストまたはセットアップメソッドが失敗した場合、それに応じてキャプチャされた出力は通常、失敗のトレースバックとともに表示されます。

pytestには、テストごとのキャプチャ方法--capture=methodであるオプションがありmethod、次のいずれかになります:fdsysまたはnopytest-sは、のショートカットであるオプションもあります。これは--capture=no、コンソールで印刷ステートメントを表示できるようにするオプションです。

pytest --capture=no     # show print statements in console
pytest -s               # equivalent to previous command

キャプチャ方法の設定またはキャプチャの無効化

pytestキャプチャを実行するには、2つの方法があります。

  1. ファイル記述子(FD)レベルのキャプチャ(デフォルト):オペレーティングシステムのファイル記述子1および2へのすべての書き込みがキャプチャされます。

  2. sysレベルキャプチャ:Pythonファイルsys.stdoutおよびsys.stderrへの書き込みのみがキャプチャされます。ファイル記述子への書き込みのキャプチャは実行されません。

pytest -s            # disable all capturing
pytest --capture=sys # replace sys.stdout/stderr with in-mem files
pytest --capture=fd  # also point filedescriptors 1 and 2 to temp file

17

PyTest文字通りすべてをミュートしたときに、スキップされたテストに関する重要な警告を正確に出力する必要がありました。

シグナルを送信するためのテストに失敗したくなかったので、次のようにハッキングを行いました。

def test_2_YellAboutBrokenAndMutedTests():
    import atexit
    def report():
        print C_patch.tidy_text("""
In silent mode PyTest breaks low level stream structure I work with, so
I cannot test if my functionality work fine. I skipped corresponding tests.
Run `py.test -s` to make sure everything is tested.""")
    if sys.stdout != sys.__stdout__:
        atexit.register(report)

このatexitモジュールを使用すると、出力ストリームを解放した後で 、印刷することができPyTestます。出力は次のようになります。

============================= test session starts ==============================
platform linux2 -- Python 2.7.3, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
rootdir: /media/Storage/henaro/smyth/Alchemist2-git/sources/C_patch, inifile: 
collected 15 items 

test_C_patch.py .....ssss....s.

===================== 10 passed, 5 skipped in 0.15 seconds =====================
In silent mode PyTest breaks low level stream structure I work with, so
I cannot test if my functionality work fine. I skipped corresponding tests.
Run `py.test -s` to make sure everything is tested.
~/.../sources/C_patch$

メッセージはPyTest、がサイレントモードの場合でも出力され、を使用して実行した場合は出力されないpy.test -sため、すべてがすでに適切にテストされています。


1
カスタムテスト指標の出力に最適です。
z0r


2

私はもともと、ここからPyTest単体テストを実行/デバッグしながらVSCodeのコンソールで印刷する方法を見つけるためにここに来ました。これは、次のlaunch.json構成で実行できます。与えられ.venvた仮想環境フォルダ。

    "version": "0.2.0",
    "configurations": [
        {
            "name": "PyTest",
            "type": "python",
            "request": "launch",
            "stopOnEntry": false,
            "pythonPath": "${config:python.pythonPath}",
            "module": "pytest",
            "args": [
                "-sv"
            ],
            "cwd": "${workspaceRoot}",
            "env": {},
            "envFile": "${workspaceRoot}/.venv",
            "debugOptions": [
                "WaitOnAbnormalExit",
                "WaitOnNormalExit",
                "RedirectOutput"
            ]
        }
    ]
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.