2017-09-29 2 views
0

を構築する方法のロガー出力の部分文字列を主張する私には、例えば、記録された何かを主張する方法の多くの例を発見しましたメッセージが構築された特定の方法からのアサーションこのテストでは、ログに記録される特定のIDだけが対象となります。パイソン - <a href="http://www.michaelpollmeier.com/python-mock-how-to-assert-a-substring-of-logger-output" rel="nofollow noreferrer">http://www.michaelpollmeier.com/python-mock-how-to-assert-a-substring-of-logger-output</a></p> <p>しかし、私は分離する方法がわからないにかかわらず、メッセージが

テストコード

mock_logger.warn.assert_called_with(
    all_match(
     contains_string('user-id'), 
     contains_string('team-id') 
    ) 
) 

は両方

量産コード1(ロガーがメッセージを組み立て)のために働く必要があり

:我々は組み立て

logger.warn(
    "Order for team %s and user %s could not be processed", 
    'team-id', 
    'user-id' 
) 

量産コード2(メッセージと例外を含む):

logger.warn(
    "Order for team {} and user {} could not be processed" 
    .format('team-id', 'user-id'), 
    ex 
) 

ですが、私は引数を取り込むか、カスタムログアペンダを設定すると、最終的なメッセージにアサーションを作るのいずれかと思っていますので、これは動作しません。


あなたが複数の引数を取り、文字列自体をフォーマットするためにあなたのwarn方法をしたい場合、私はIDE

答えて

0

でコードを書いていないように私は、任意のタイプミス/潜在的な構文エラーを無視してくださいall_matchのようなマッチャーはうまくいかないと思います。マッチャーは1つの引数にしかマッチしません。

あなたはassert_called_with最初引数としてall_matchを渡しているので、それだけでmock_logger.warnへの呼び出しに最初の引数を一致させることができます。そのため、テストコードは生産コード1ではなく生産コード2に渡されます。

生産コード2では、warnの最初の引数は文字列"Order for team team-id and user user-id could not be processed"です。モックは最初の引数をall_matchに渡すので、探しているものが見つかります。

生産コード1では、warnの最初の引数は"Order for team %s and user %s could not be processed"です。それはすべてall_matchが知っているものです。 2番目と3番目の引数には、all_matchで検索する文字列が含まれていますが、アクセスできません。

マッチャをassert_called_withに渡す代わりに、モックの呼び出しを手動でチェックすることはどちらの場合でも有効です。ここで私が言いたいの洗練が、読みやすい実装です:

mock_logger = unittest.Mock() 
... 
# Call production code 
... 
calls = mock_logger.warn.call_args_list # gets a list of calls made to the mock 

first_call = calls[0] # each call object in call_args_list is a tuple containing 2 tuples: ((positional args), (keyword args)). Let's grab the first one. 

arguments = first_call[0] # the positional arguments are the first tuple in the call 

if len(arguments) == 1: # If warn got 1 argument, it's a string. Look for 'team-id' and 'user-id' in that argument 
    self.assertIn('team-id', arguments[0]) 
    self.assertIn('user-id', arguments[0]) 
elif len(arguments) == 3: # if warn got 3 arguments, 'team-id' and 'user-id' should have been the 2nd and 3rd arguments. 
    self.assertEqual("Order for team %s and user %s could not be processed", arguments[0]) 
    self.assertEqual('team-id', arguments[1]) 
    self.assertEqual('user-id', arguments[2]) 

あなたが本当にマッチャーを使用したい場合、あなたは常にあなたがwarnを呼び出す前に、文字列をフォーマットする意味logger.warnに単一の文字列を渡す必要があります。

関連する問題

 関連する問題