web-dev-qa-db-ja.com

pytestでコンソールに印刷する方法は?

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

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.

標準出力コンソールには何も印刷されません(通常の進行状況と、いくつのテストが成功/失敗したかだけです)。

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

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

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

印刷ステートメントを表示させる方法を知っていますか?

111
BBedit

デフォルトでは、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 ======================
136
tbekolay

-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 Shellコマンドを実行してテストを実行できます。

それはややハック的な方法ですが、必要なものかもしれません:結局、TDDはものをいじり、準備ができたらきれいで静かなままにすることを意味します:-)。

42
dmitry_romanov

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

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

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)

atexitname__モジュールを使用すると、afterを出力できますPyTestname__は出力ストリームをリリースしました。出力は次のようになります。

============================= 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$

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

10
dmitry_romanov

短い答え

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

pytest -s

詳細な回答

ドキュメント から:

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

pytestにはオプション--capture=methodがあり、methodはテストごとのキャプチャメソッドであり、fdsys、またはnoのいずれかです。 pytestには、-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
7
lmiguelvargasf

pytest docs によると、pytest --capture=sysは動作するはずです。テスト内で標準出力をキャプチャする場合は、capsysフィクスチャを参照してください。