Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Mock

Dan Langer
March 14, 2012

 Mock

Created for the Django Toronto meetup, a quick tour through the Python mock package.

Dan Langer

March 14, 2012
Tweet

More Decks by Dan Langer

Other Decks in Technology

Transcript

  1. mock==0.8.0

    View Slide

  2. Who am I?
    Dan Langer
    @dlanger
    [email protected]
    daniel.langer.me

    View Slide

  3. View Slide

  4. View Slide

  5. >> import mock
    >> dir(mock)
    ['Mock', 'patch', ...]

    View Slide

  6. >> from mock import Mock

    View Slide

  7. Mocks all the way down
    >> k = Mock()
    >> k.foo.bar

    >> k.foo.bar

    View Slide

  8. Configure your mocks
    >> from django.contrib.auth.models
    import User
    >> user1_mock = Mock()
    >> user1_mock.foo

    >> user2_mock = Mock(spec=User)
    >> user2_mock.foo
    AttributeError: ...

    View Slide

  9. Configure your mocks
    >> rmock = Mock(return_value=5)
    >> rmock(), rmock(4), rmock("W")
    (5, 5, 5)
    >> smock = Mock(side_effect=[1,2])
    >> smock(), smock()
    (1, 2)
    >> emock = Mock(side_effect=Exception)
    >> emock()
    Exception: ...

    View Slide

  10. Inspect your mocks
    >> imock = Mock(return_value=None)
    >> imock()
    >> imock.call_count
    1
    >> imock(1, 2, 3, demo="ok")
    >> imock.call_args_list
    [call(1), call(1,2,3,demo='ok')]

    View Slide

  11. >> from mock import patch

    View Slide

  12. Daniel Coomber

    View Slide

  13. Patch all the things
    # utils.py
    def load_token(user)
    r = StrictRedis(host=...)
    [...]
    raw_token = r.rpop(token_id)
    return '--'.join([raw_token, ...])
    # tests.py
    def test_load_token(self):
    redis_mock = Mock()
    redis_mock.return_value.rpop \
    .return_value = 'TEST_TOKEN'
    with patch('utils.StrictRedis', redis_mock):
    load_token(self.test_user)
    self.assertEqual(...)

    View Slide

  14. Patch celery
    # tasks.py
    @task
    def process_chunk(chunk):
    pass
    @task
    def process_file(file):
    tasks = []
    for ...
    st = process_chunk.subtask(chunk)
    tasks.append(st)
    process = TaskSet(tasks=tasks)
    process.apply_async()

    View Slide

  15. Patch celery
    # tests.py
    def test_process_file__two_subtasks(self):
    pc_mock = Mock()
    with patch('tasks.process_chunk',
    pc_mock):
    process_file.delay(...)
    self.assertEqual(pc_mock.call_count, 2)
    #Fails

    View Slide

  16. Patch celery
    # tests.py
    def test_process_file__two_subtasks(self):
    pc_mock = Mock()
    with patch('tasks.process_chunk.subtask',
    pc_mock):
    process_file.delay(...)
    self.assertEqual(pc_mock.call_count, 2)

    View Slide

  17. Patch built-ins
    # utils.py
    import message_defs
    def load_defaults(id)
    if getattr(message_defs, id, None):
    [...]
    # tests.py
    def test_load_defaults(self):
    with patch('__builtins__.getattr',
    return_value='Hi'):
    load_defaults('welcome')
    self.assertEqual(...)

    View Slide

  18. Patch built-ins
    # utils.py
    import message_defs
    def load_defaults(id)
    if getattr(message_defs, id, None):
    [...]
    # tests.py
    def test_load_defaults(self):
    with patch('utils.getattr',
    create=True,
    return_value='Hi'):
    load_defaults('welcome')
    self.assertEqual(...)

    View Slide

  19. Patch Django
    def test_template:
    mock_get_template = Mock(
    return_value=Template("Hi {{ username }}"))
    with patch('package.module.get_template',
    mock_get_template):
    [...]
    def test_verify_user(self):
    mock_get = Mock()
    mock_get.return_value = Mock(spec=User)
    with patch('utils.User.objects.get',
    mock_get):
    [...]

    View Slide

  20. Patch the ORM...sparingly
    # User.objects.filter(...).exclude(...) \
    # .order_by(...)
    def test_user_filter(self):
    mock_filter = Mock()
    mock_filter.return_value.exclude \
    .return_value.order_by.return_value = [...]
    with patch('utils.User.objects.filter',
    mock_filter):
    [...]

    View Slide

  21. Keep Reading
    @decorator syntax
    create_autospec
    MagicMock [...]
    http://www.voidspace.org.
    uk/python/mock/

    View Slide