12

コレクション内の各アイテムに対して一連のメソッドを呼び出すコードが少しあり、各メソッドは成功 = True/失敗 = False を示すブール値を返します。

def monkey(some_collection, arg1, arg2):
    for item in some_collection:
        if not item.foo(arg1, arg2):
            continue
        if not item.bar(arg1, arg2):
            continue
        if not item.baz(arg1, arg2):
            continue

そして、これが私の単体テストの例です:

import mock
def TestFoo(unittest.TestCase):
    def test_monkey(self):
        item = MagicMock()
        some_collection = [item]
        collection_calls = []
        foo_call = mock.call().foo(some_collection, 1, 2)
        bar_call = mock.call().bar(some_collection, 1, 2)
        baz_call = mock.call().baz(some_collection, 1, 2)
        collection_calls = [foo_call, bar_call, baz_call]                   
        my_module.monkey(some_collection, 1, 2)
        item.assert_has_calls(collection_calls) # requires the correct call order/sequence

実際の通話

  1. call().foo(<MagicMock id='12345'>, 1, 2)
  2. call().foo.__nonzero__()

...

注: この単体テストは、__nonzero__()メソッド呼び出しを確認しているため失敗します。

質問

ゼロ以外のメソッド呼び出しを追加するのはなぜですか?

明確化

Python 3.3 の時点で stdlib に含まれている mockを使用しています。

4

1 に答える 1

21

短い答え:

モックされた関数に、返される明示的なreturn_valueまたはside_effectがない場合、Pythonがモックの真実性を評価しようとするときに、これが表示されます。モックに1つあることを確認してください。

次のいずれかで初期化します。

item = MagicMock(return_value=True)

または、次の場所に1つ追加します。

item.return_value = True

説明:

あなたがするときif not x:、あなたはおそらく考えていif x is Falseます。

Pythonは実際にはこれを行いません-これはif bool(x) is False(これはPythonの真実性の概念です-値がTrueまたはに評価されるFalse)、実際には(または3.xで)bool(x)の呼び出しです。x.__nonzero__()x.__bool__()

これはPythonの優れifた動作を提供するためです。そうするとif []:、多くの言語が任意のオブジェクトをとして扱いますTrueが、Pythonはコードを読み取り可能にするように設計されているため、委任され、リストの__nonzero__()メソッドFalseは空の場合に返されます。これにより、より自然に読み取るコードが増え、これらの呼び出しが表示される理由が説明されます。

于 2012-12-26T21:09:26.040 に答える