web-dev-qa-db-ja.com

ロギングが特定の文字列で呼び出されたことを表明します

unittestを使用して、作成したSimpleXMLRPCServerのいくつかの関数をテストしようとしています。 Mockと一緒に、ifステートメントに達したときに特定のメッセージがログに記録されていることを表明しようとしていますが、それを機能させることができません。 StackOverflowまたはGooglingで見つけたさまざまな回答を実装しようとしましたが、それでもうまくいきません。テストケースで行う呼び出しは次のとおりです。

def test_listen_for_tasks(self):
    el = {'release': 'default', 'component': None}
    for i in range(50):
        self.server._queue.put(el)
    ServerThread.listen_for_tasks(self.server, 'bla', 'blabla')
    with mock.patch('queue_server.logging') as mock_logging:
        mock_logging.warning.assert_called_with('There are currently {}'
                                                ' items in the queue'.format(
                                                 str(len(self.server._queue.queue))))

サーバーの機能は次のとおりです。

def listen_for_tasks(self, release, component):
    item = {'release': release, 'component': component}
    for el in list(self._queue.queue):
        if self.is_request_duplicate(el, item):
            logger.debug('Already have a request'
                         ' for this component: {}'.format(item))
            return
    self._queue.put(item, False)
    if len(self._queue.queue) > 50:
        logger.warning('There are currently {}'
                       ' items in the queue'.format(
                        str(len(self._queue.queue))))

これが機能しない理由はありますか?私はPythonでのユニットテストに不慣れで、ロガーが何かをしたと主張することは直面する可能性のある最大の問題のように思われるので、コードで本当に単純なことを台無しにしたかもしれません。助けていただければ幸いです!

編集:完全を期すために、ここにテスト出力と失敗があります:

.No handlers could be found for logger "queue_server"
F


FAIL: test_listen_for_tasks (__main__.TestQueueServer)

Traceback (most recent call last):
  File "artifacts_generator/test_queue_server.py", line 46, in   test_listen_for_tasks
str(len(self.server._queue.queue))))
  File "/home/lugiorgi/Desktop/Code/publisher/env/local/lib/python2.7/site-packages/mock/mock.py", line 925, in assert_called_with
raise AssertionError('Expected call: %s\nNot called' % (expected,))
AssertionError: Expected call: warning('There are currently 51 items in the queue')
Not called

Ran 2 tests in 0.137s

FAILED (failures=1)
14
Luca Giorgi

最初オブジェクトをモックし、次にテストする関数を呼び出す必要があります。

オブジェクトをモックするときは、変数名ではなく、モックするオブジェクトの完全なパッケージ名とオブジェクト/関数名も指定する必要があります。

最後に、patchのデコレータ形式を使用する方が便利な場合がよくあります。

したがって、たとえば:

logger = logging.getLogger(__name__)

def my_fancy_function():
    logger.warning('test')

@patch('logging.Logger.warning')
def test_my_fancy_function(mock):
    my_fancy_function()
    mock.assert_called_with('test')

# if you insist on using with:
def test_my_fancy_function_with_with():
    with patch('logging.Logger.warning') as mock:
        my_fancy_function()
        mock.assert_called_with('test')
14
Thom Wiggers

python 3.4なので、unittest.TestCaseクラスメソッドを使用できます assertLogs

import logging
import unittest


class LoggingTestCase(unittest.TestCase):
    def test_logging(self):
        with self.assertLogs(level='INFO') as log:
            logging.info('Log message')
            self.assertEqual(len(log.output), 1)
            self.assertEqual(len(log.records), 1)
            self.assertIn('Log message', log.output[0])
18
nes