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
を使用したいと思います。
印刷ステートメントを表示させる方法を知っていますか?
デフォルトでは、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 ======================
-s
オプションを使用すると、すべての関数の出力が出力されますが、出力が多すぎる可能性があります。
特定の出力が必要な場合は、言及したドキュメントページにいくつかの提案があります。
関数の最後にassert False, "dumb assert to make PyTest print my stuff"
を挿入すると、テストの失敗による出力が表示されます。
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はものをいじり、準備ができたらきれいで静かなままにすることを意味します:-)。
PyTest
name__が文字通り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)
atexit
name__モジュールを使用すると、afterを出力できますPyTest
name__は出力ストリームをリリースしました。出力は次のようになります。
============================= 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
name__がサイレントモードの場合でもメッセージが出力され、py.test -s
を使用して何かを実行した場合はnotが出力されるため、すべてがすでに十分にテストされています。
-s
オプションを使用します。
pytest -s
ドキュメント から:
テストの実行中、stdoutおよびstderrに送信された出力がキャプチャされます。テストまたはセットアップメソッドが失敗した場合、通常、キャプチャされた出力が失敗トレースバックとともに表示されます。
pytest
にはオプション--capture=method
があり、method
はテストごとのキャプチャメソッドであり、fd
、sys
、またはno
のいずれかです。 pytest
には、-s
のショートカットであるオプション--capture=no
もあります。これは、コンソールで印刷ステートメントを表示できるオプションです。
pytest --capture=no # show print statements in console
pytest -s # equivalent to previous command
pytest
がキャプチャを実行できる方法は2つあります。
ファイル記述子(FD)レベルのキャプチャ(デフォルト):オペレーティングシステムファイル記述子1および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
pytest docs によると、pytest --capture=sys
は動作するはずです。テスト内で標準出力をキャプチャする場合は、capsysフィクスチャを参照してください。