Slide 1

Slide 1 text

Testing with unittest.mock Ana Hristova

Slide 2

Slide 2 text

♥ Every tester has the heart of a developer

Slide 3

Slide 3 text

Crowd Investment Platform CONNECTING INVESTORS AND ENTREPRENEURS THROUGH FUNDING ana@fundedbyme.com

Slide 4

Slide 4 text

No content

Slide 5

Slide 5 text

Sweden

Slide 6

Slide 6 text

unittest.mock Testing library

Slide 7

Slide 7 text

Part of the Python Standard Library as of Python 3.3 unittest.mock

Slide 8

Slide 8 text

For older versions: unittest.mock $ pip install mock

Slide 9

Slide 9 text

unittest.mock helps you create mock objects and make assertions about them

Slide 10

Slide 10 text

How is this helpful?

Slide 11

Slide 11 text

You want to test code that depends on the " date or time

Slide 12

Slide 12 text

You are building a shiny new app … # $ % % % % % & ' ( )

Slide 13

Slide 13 text

Please wait… … while your tests are running *

Slide 14

Slide 14 text

Mock MagicMock patch( )

Slide 15

Slide 15 text

Mock objects Callable

Slide 16

Slide 16 text

Mock objects Create attributes on demand

Slide 17

Slide 17 text

Mock objects Record how you use the attributes

Slide 18

Slide 18 text

Allow you to set return values or limit the available attributes Mock objects

Slide 19

Slide 19 text

Examples

Slide 20

Slide 20 text

>>> class Comment: ... ... def create(self, text, parent=None): ... pass ... comment = Comment()

Slide 21

Slide 21 text

>>> comment.create = Mock(return_value=True) >>> comment.create(text=‘hello') True >>> comment.create. \ ... assert_called_once_with(text=‘hello’) >>> comment.create.called True >>> comment.create.call_args call(text='hello') >>> comment.call_count 1

Slide 22

Slide 22 text

>>> mock = Mock() >>> mock >>> mock.method >>> mock.assetr_called_with(keyword=None)

Slide 23

Slide 23 text

... AttributeError: Mock object has no attribute 'remove' >>> comment.remove >>> from unittest.mock import create_autospec >>> >>> comment = create_autospec(Comment)

Slide 24

Slide 24 text

side effects

Slide 25

Slide 25 text

>>> comment.create.side_effect = \ ... ConnectionError(“Connection refused”) >>> ... ConnectionError: Connection refused >>> comment.create.mock_calls [call(parent=None, text='Hello')] >>> >>> comment.create(text="Hello", parent=None)

Slide 26

Slide 26 text

magic methods Mocking

Slide 27

Slide 27 text

>>> mock = Mock() >>> mock.__len__ = Mock() >>> mock.__len__.return_value = 42 >>> len(mock) 42 ! !

Slide 28

Slide 28 text

MagicMock with default implementations of magic methods Subclass of Mock

Slide 29

Slide 29 text

>>> mock = MagicMock() >>> int(mock) 1 >>> len(mock) 0 >>> list(mock) [] >>> mock.__int__.called True

Slide 30

Slide 30 text

patch( ) Used to patch objects within the scope of the test

Slide 31

Slide 31 text

#event.py from datetime import date ! class Event(): ! def get_state(self): if self.end_date < date.today(): return "PAST" if self.start_date > date.today(): return "FUTURE" if self.start_date <= date.today() <= self.end_date: return "CURRENT"

Slide 32

Slide 32 text

#test.py from datetime import date ! class EventTests(TestCase): def setUp(self): self.pycon = Event() self.pycon.start_date = date(2014, 5, 20) self.pycon.end_date = date(2014, 5, 21) ! @patch('event.date') def test_event_has_passed(self, mock_date): mock_date.today.return_value = date(2014, 5, 22) assert self.pycon.get_state() == "PAST"

Slide 33

Slide 33 text

@patch('event.date') def test_event_has_passed(self, mock_date): mock_date.today.return_value = date(2014, 5, 22) assert self.pycon.get_state() == "PAST"

Slide 34

Slide 34 text

class UserProfileSaveTests(TestCase): ! def setUp(self): self.profile = UserProfileFactory.build(user=UserFactory()) ! ! @patch("notifications.tasks.subscribe_to_newsletter.delay") def test_subscribe_to_newsletter(self, subscribe_mock): self.profile.newsletter = True self.profile.save() subscribe_mock.assert_called_once_with(self.profile.user)

Slide 35

Slide 35 text

Mock wisely!

Slide 36

Slide 36 text

@anhristova + , anah