Slide 1

Slide 1 text

mock==0.8.0

Slide 2

Slide 2 text

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

Slide 3

Slide 3 text

No content

Slide 4

Slide 4 text

No content

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

>> from mock import Mock

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

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: ...

Slide 9

Slide 9 text

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: ...

Slide 10

Slide 10 text

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')]

Slide 11

Slide 11 text

>> from mock import patch

Slide 12

Slide 12 text

Daniel Coomber

Slide 13

Slide 13 text

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(...)

Slide 14

Slide 14 text

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()

Slide 15

Slide 15 text

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

Slide 16

Slide 16 text

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)

Slide 17

Slide 17 text

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(...)

Slide 18

Slide 18 text

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(...)

Slide 19

Slide 19 text

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): [...]

Slide 20

Slide 20 text

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): [...]

Slide 21

Slide 21 text

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