46

私はもう試した

from mock import Mock
import __builtin__

__builtin__.print = Mock()

しかし、それは構文エラーを引き起こします。私もそのようにパッチを当ててみました

@patch('__builtin__.print')
def test_something_that_performs_lots_of_prints(self, mock_print):

    # assert stuff

これを行う方法はありますか?

4

11 に答える 11

54

すでに受け入れられている答えがあることは知っていますが、その問題に対するより簡単な解決策があります-python 2.xで印刷をモックします。答えはモック ライブラリ チュートリアルにあります: http://www.voidspace.org.uk/python/mock/patch.htmlで、次のとおりです。

>>> from StringIO import StringIO
>>> def foo():
...     print 'Something'
...
>>> @patch('sys.stdout', new_callable=StringIO)
... def test(mock_stdout):
...     foo()
...     assert mock_stdout.getvalue() == 'Something\n'
...
>>> test()

もちろん、次のアサーションも使用できます。

self.assertEqual("Something\n", mock_stdout.getvalue())

単体テストでこのソリューションを確認しましたが、期待どおりに機能しています。これが誰かに役立つことを願っています。乾杯!

于 2015-07-01T21:08:36.317 に答える
18

printは python 2.x のキーワードで、属性として使用すると SyntaxError が発生します。from __future__ import print_functionファイルの先頭で使用することで、これを回避できます。

注:ステートメントを無効setattrにしない限り、変更した print 関数は呼び出されないため、単純に を使用することはできません。print

編集:変更した関数を使用するfrom __future__ import print_functionすべてのファイルで必要です。そうしないと、ステートメントによってマスクされます。printprint

于 2012-10-21T15:13:04.523 に答える
3

print2.x の関数ではなく 2.x のステートメントに固執したい場合は、代わりにprint()自分のステートメントをモックできますsys.stdout

おそらく次のような方法で、ダミーの「ファイル」を作成します。

class Writable(object):
    """Class which has the capability to replace stdout."""
    newwrite = None
    def __init__(self, oldstdout, newwrite=None):
        self.oldstdout = oldstdout
        if newwrite is not None:
            self.newwrite = newwrite
    def write(self, data):
        self.newwrite(self.oldstdout, data)
    @classmethod
    def subclass(cls, writefunc):
        newcls = type('', (cls,),
            dict(write=lambda self, data: writefunc(self.oldstdout, data)
        return newcls

このクラスは、印刷データを取得する書き込み関数と組み合わせることを想定しています。この書き込み関数は 2 つの引数を取ることになっています。最初の引数は「古い stdout」を最後に印刷するために使用され、もう 1 つはデータ用です。

取りましょう

def mywrite(sink, data):
    sink.write(data.encode("hex"))

そのために。

今、あなたはすることができます

import sys
sys.stdout = Writable(sys.stdout, mywrite)

またはあなたができる

@Writable.subclass
def mywritable(sink, data)
    sink.write(data.encode("hex"))

sys.stdout = mywritable(sys.stdout)

2 番目のバージョンは少しトリッキーです:Writable指定された関数を代わりに作成された新しいクラスのメソッドに変換し、指定された関数が由来する名前に入れるデコレータ関数の助けを借りて のサブクラスを作成します。

その後、「古い標準出力」を引数としてインスタンス化できる新しいクラスがあり、その後置き換えることができsys.stdoutます。

于 2012-10-21T19:45:53.987 に答える
3

私のバージョン。

テストされたプログラム (例: pp.py):

from __future__ import print_function

def my_func():
    print('hello')

テストプログラムでは:

def test_print(self):
    from pp import my_func
    from mock import call
    with mock.patch('__builtin__.print') as mock_print:
       my_func()
       mock_print.assert_has_calls(
            [
                call('hello')
            ]
        )
于 2014-03-26T12:23:22.810 に答える
0

lcq が言うように、printはキーワードです。では、実際に Python 2.7.3 で print のパッチ適用/モック化に成功したとしたら、それが何を意味するかを考えてみてください。次のようなコードがあります。

print "Hi."

に変わります:

<MagicMock id='49489360'> "Hi."

この方法では MagicMock オブジェクトにアクセスできないため、構文エラーが発生します。

それで...ええ。Python3 の print関数または sys.stdout のみをモックできます。

于 2013-01-03T02:38:39.177 に答える
0

まず、モジュールが呼び出され__builtins__、インポートする必要はありません。

現在、Python 2 ではprintキーワードであるため、属性名として直接使用することはできません。setattr/を使用getattrして回避できます。

getattr(__builtins__, "print")

もう 1 つのオプションは、from __future__ import print_functionPython がモジュールを Python 3 構文に解析する方法を変更する which を使用することです。

于 2012-10-21T15:04:10.023 に答える