SlideShare a Scribd company logo
1 of 35
Download to read offline
Managing mocks
The how, why and when of mocking in Python
Helen Sherwood-Taylor
EuroPython
21st July 2016
What is a mock?
A fake object that replaces a real object
Control and isolate the test's environment
Why?
Deterministic tests
Control the test inputs
Faster test suites
unittest.mock
>>> from unittest import mock
# Or, for Python <3.3
$ pip install mock
>>> import mock
also known as the mock library
written by Michael Foord
Added to Python in 3.3
Rolling backport for earlier Pythons
not just for unittest
Mock objects
>>> from unittest.mock import Mock
>>> mock_talk = Mock(conference='EuroPython')
>>> mock_talk.conference
'EuroPython'
>>> mock_talk.speaker
<Mock name='mock.speaker' id='139910592223552'>
>>> mock_talk.speaker.name
<Mock name='mock.speaker.name' id='139910592222208'>
>>> mock_talk.speaker.name = 'Helen'
>>> mock_talk.speaker.name
'Helen'
Properties of Mocks
Callable Mocks
>>> mock_talk.speaker.get_twitter_status()
<Mock name='mock.speaker.get_twitter_status()'>
>>> mock_talk.speaker.
get_twitter_status.return_value = 'Eating pintxos'
>>> mock_talk.speaker.get_twitter_status()
'Eating pintxos'
return_value
Side effects
An exception
>>> mock_func = Mock()
>>> mock_func.side_effect = ValueError
>>> mock_func()
Traceback (most recent call last):
...
ValueError
A function
>>> mock_func.side_effect = lambda x: x*2
>>> mock_func(2)
4
Multiple side effects
A list of return values and exceptions
>>> mock_func.side_effect = [1, ValueError, 2]
>>> mock_func()
Traceback (most recent call last):
...
ValueError
>>> mock_func()
Traceback (most recent call last):
...
StopIteration
>>> mock_func()
1
>>> mock_func()
2
What was called?
assert_called_with(*args, **kwargs)
assert_called_once_with(*args, **kwargs)
assert_any_call(*args, **kwargs)
assert_has_calls((call(*args, **kwargs), ...))
assert_not_called()
>>> from unittest.mock import Mock, call
>>> mock_func = Mock()
>>> mock_func(1)
>>> mock_func(2)
>>> mock_func.assert_called_with(2)
>>> mock_func.assert_has_calls([call(1), call(2)])
Beware versions
assert_not_called
>>> mock_func = Mock()
>>> mock_func()
>>> mock_func.assert_not_called()
<Mock name='mock.assert_not_called()' id='139758629541536'>
python 3.5
>>> mock_func = Mock()
>>> mock_func()
>>> mock_func.assert_not_called()
...
AssertionError: Expected 'mock' to not have been called. Called 1 times.
python 3.4
assert safety
python 3.5
>>> from unittest.mock import Mock, call
>>> mock_func = Mock()
>>> mock_func.assert_called()
...
AttributeError: assert_called
Detects non existent assertion calls
disable it with unsafe=True
assert*
assret*
Matching call args
mock.ANY doesn't care
>>> from unittest.mock import Mock, ANY
>>> mock_func = Mock()
>>> mock_func(25)
>>> mock_func.assert_called_with(ANY)
Comparisons
Use comparison objects for more control
class MultipleMatcher:
def __init__(self, factor):
self.factor = factor
def __eq__(self, other):
return other % self.factor == 0
def __repr__(self):
return 'Multiple of {}'.format(self.factor)
>>> mock_func = Mock()
>>> mock_func(25)
>>> mock_func.assert_called_with(MultipleMatcher(5))
>>> mock_func.assert_called_with(MultipleMatcher(4))
...
AssertionError: Expected call: mock_func(Multiple of 4)
Actual call: mock_func(25)
Call inspection
Lower level inspection of calls
called - was it called?
call_count - how many times?
call_args - args/kwargs of last call
call_args_list - args/kwargs of all calls
How to use all this
1. Create / insert a mock
2. Set up inputs / environment
3. Run the code under test
4. Assert expectations met
patch
Get access to anything
>>> from unittest.mock import patch
>>> patch('requests.get')
<unittest.mock._patch object at 0x7f7a2af03588>
creates a MagicMock
patch decorator
import requests
def get_followers(username):
response = requests.get(
'https://api.github.com/users/%s' % username
)
return response.json()['followers']
@patch('requests.get')
def test_get_followers(mock_get):
mock_get.return_value.json.return_value = {'followers': 100}
assert get_followers('somebody') == 100
mock is a parameter to the test method
>>> print(get_followers('helenst'))
25
patch context manager
with patch('requests.get') as mock_get:
mock_get.return_value.json.return_value = {'followers': 100}
assert get_followers('somebody') == 100
patch: manual control
patcher = patch('requests.get')
mock_get = patcher.start()
mock_get.return_value.json.return_value = {'followers': 100}
assert get_followers('somebody') == 100
patcher.stop()
Where to patch
# github_utils.py
import requests
def get_followers(username):
response = requests.get(
'https://api.github.com/users/%s' % username
)
return response.json()['followers']
import github_utils
with patch('requests.get') as mock_get:
mock_get.return_value.json.return_value = {'followers': 100}
# This will succeed.
assert github_utils.get_followers('somebody') == 100
Where to patch: 2
# file: github_utils2
from requests import get
def get_followers(username):
response = get(
'https://api.github.com/users/%s' % username
)
return response.json()['followers']
import github_utils2
with patch('requests.get') as mock_get:
mock_get.return_value.json.return_value = {'followers': 100}
assert github_utils2.get_followers('somebody') == 100
AssertionError: 25 != 100
Where to patch: the answer
patch('github_utils2.get')
import github_utils2
with patch('github_utils2.get') as mock_get:
mock_get.return_value.json.return_value = {'followers': 100}
# This will succeed.
assert github_utils2.get_followers('somebody') == 100
Patch the imported path
“ ensure that you patch the name used by the system under test.
patch.object
Attach mocks to an object
class User:
def is_birthday(self):
# ...
pass
def greet(self):
if self.is_birthday():
return 'happy birthday'
else:
return 'hello'
user = User()
with patch.object(user, 'is_birthday', return_value=True):
# user.is_birthday is a MagicMock that returns True
# Check the outcome
assert user.greet() == 'happy birthday'
Mock the time
>>> patch("datetime.date.today").start()
...
TypeError: can't set attributes of built-in/extension type 'datetime.date'
date is written in C so you can't mock its attributes.
>>> patch('datetime.date').start()
<MagicMock name='date' id='140222796874696'>
But you can mock the whole thing.
Is it my birthday?
from datetime import date
def its_my_birthday():
today = date.today()
return today.month == 3 and today.day == 19
import birthday
@patch('birthday.date')
def test_birthday_3(mock_date):
mock_date.today.return_value = date(2016, 3, 19)
assert birthday.its_my_birthday()
freezegun
$ pip install freezegun
from freezegun import freeze_time
import birthday
@freeze_time('2016-03-19')
def test_birthday_4():
assert birthday.its_my_birthday()
Mock the filesystem
from unittest.mock import mock_open
open_mock = mock_open(
read_data='look at all my file contents'
)
with patch('__main__.open', open_mock, create=True):
with open('myfile') as file:
assert file.read() == 'look at all my file contents'
mock_open will help you out here.
But you can't iterate
Iterate a mock file
with patch('__main__.open', mock_open(), create=True) as open_mock:
mock_file = open_mock.return_value.__enter__.return_value
mock_file.__iter__.return_value = ([
'line one', 'line two'
])
with open('myfile') as file:
assert list(file) == ['line one', 'line two']
with open('myfile') as myfile:
for line in myfile:
print(line)
Mock a property
class Person:
@property
def is_birthday(self):
today = date.today()
return self.dob.month == today.month and self.dob.day == today.day
def greet(self):
return 'Happy birthday!' if self.is_birthday else 'Good morning!'
# Patching the object doesn't work.
>>> with patch.object(person, 'is_birthday', return_value=True):
... assert person.greet() == 'Happy birthday!'
...
AttributeError: <__main__.Person object at 0x7f9875ea73c8>
does not have the attribute 'is_birthday'
How to mock a property
with patch.object(
Person,
'is_birthday',
new_callable=PropertyMock,
return_value=True
):
assert person.greet() == 'Happy birthday!'
use new_callable
patch the class
Example: delay loop
def retry_with_delay(func):
delay = 1
while True:
try:
return func()
except DatabaseError:
time.sleep(delay)
delay *= 2
@patch('time.sleep')
def test_third_time_lucky(mock_sleep):
mock_func = Mock(side_effect=[DatabaseError, DatabaseError, 'Yay'])
result = retry_with_delay(mock_func)
assert mock_func.call_count == 3
mock_sleep.assert_has_calls([
call(1),
call(2),
])
assert result == 'Yay'
When to mock?
Current time
say happy birthday to a user
Simulated failure
(what happens when the disk is full?)
Slowness
e.g. time.sleep
Randomness
Remote APIs
any data you want
What about the rest?
Purity / Design
Speed
Pinpoint failures
Realistic coverage
Harder to read
Harder to write
Meaningless?
Doesn't test inter-layer stuff
Should I mock the other layers?
YES NO
Further reading
Book: http://www.obeythetestinggoat.com/
Talk: Gary Bernhardt - Fast Test, Slow Test
https://docs.python.org/3/library/unittest.mock.html
Thank you!
Twitter: @helenst
Github: @helenst
http://helen.st/
https://github.com/helenst/managing_mocks

More Related Content

What's hot

Smarter Testing with Spock
Smarter Testing with SpockSmarter Testing with Spock
Smarter Testing with SpockDmitry Voloshko
 
merged_document_3
merged_document_3merged_document_3
merged_document_3tori hoff
 
Fear no fragments
Fear no fragmentsFear no fragments
Fear no fragmentsDipo Areoye
 
The Ring programming language version 1.5.4 book - Part 79 of 185
The Ring programming language version 1.5.4 book - Part 79 of 185The Ring programming language version 1.5.4 book - Part 79 of 185
The Ring programming language version 1.5.4 book - Part 79 of 185Mahmoud Samir Fayed
 
Integration Project Inspection 3
Integration Project Inspection 3Integration Project Inspection 3
Integration Project Inspection 3Dillon Lee
 
Programming JVM Bytecode with Jitescript
Programming JVM Bytecode with JitescriptProgramming JVM Bytecode with Jitescript
Programming JVM Bytecode with JitescriptJoe Kutner
 
The Ring programming language version 1.6 book - Part 82 of 189
The Ring programming language version 1.6 book - Part 82 of 189The Ring programming language version 1.6 book - Part 82 of 189
The Ring programming language version 1.6 book - Part 82 of 189Mahmoud Samir Fayed
 
The Ring programming language version 1.5.3 book - Part 88 of 184
The Ring programming language version 1.5.3 book - Part 88 of 184The Ring programming language version 1.5.3 book - Part 88 of 184
The Ring programming language version 1.5.3 book - Part 88 of 184Mahmoud Samir Fayed
 
DjangoCon US 2011 - Monkeying around at New Relic
DjangoCon US 2011 - Monkeying around at New RelicDjangoCon US 2011 - Monkeying around at New Relic
DjangoCon US 2011 - Monkeying around at New RelicGraham Dumpleton
 
Effective Modern C++ - Item 35 & 36
Effective Modern C++ - Item 35 & 36Effective Modern C++ - Item 35 & 36
Effective Modern C++ - Item 35 & 36Chih-Hsuan Kuo
 
Threads, Queues, and More: Async Programming in iOS
Threads, Queues, and More: Async Programming in iOSThreads, Queues, and More: Async Programming in iOS
Threads, Queues, and More: Async Programming in iOSTechWell
 
The Ring programming language version 1.5.1 book - Part 75 of 180
The Ring programming language version 1.5.1 book - Part 75 of 180The Ring programming language version 1.5.1 book - Part 75 of 180
The Ring programming language version 1.5.1 book - Part 75 of 180Mahmoud Samir Fayed
 
JVM Mechanics: Understanding the JIT's Tricks
JVM Mechanics: Understanding the JIT's TricksJVM Mechanics: Understanding the JIT's Tricks
JVM Mechanics: Understanding the JIT's TricksDoug Hawkins
 
Ownership System in Rust
Ownership System in RustOwnership System in Rust
Ownership System in RustChih-Hsuan Kuo
 
The Ring programming language version 1.9 book - Part 91 of 210
The Ring programming language version 1.9 book - Part 91 of 210The Ring programming language version 1.9 book - Part 91 of 210
The Ring programming language version 1.9 book - Part 91 of 210Mahmoud Samir Fayed
 

What's hot (18)

Smarter Testing with Spock
Smarter Testing with SpockSmarter Testing with Spock
Smarter Testing with Spock
 
merged_document_3
merged_document_3merged_document_3
merged_document_3
 
How to fake_properly
How to fake_properlyHow to fake_properly
How to fake_properly
 
Fear no fragments
Fear no fragmentsFear no fragments
Fear no fragments
 
The Ring programming language version 1.5.4 book - Part 79 of 185
The Ring programming language version 1.5.4 book - Part 79 of 185The Ring programming language version 1.5.4 book - Part 79 of 185
The Ring programming language version 1.5.4 book - Part 79 of 185
 
Integration Project Inspection 3
Integration Project Inspection 3Integration Project Inspection 3
Integration Project Inspection 3
 
My java file
My java fileMy java file
My java file
 
Programming JVM Bytecode with Jitescript
Programming JVM Bytecode with JitescriptProgramming JVM Bytecode with Jitescript
Programming JVM Bytecode with Jitescript
 
The Ring programming language version 1.6 book - Part 82 of 189
The Ring programming language version 1.6 book - Part 82 of 189The Ring programming language version 1.6 book - Part 82 of 189
The Ring programming language version 1.6 book - Part 82 of 189
 
The Ring programming language version 1.5.3 book - Part 88 of 184
The Ring programming language version 1.5.3 book - Part 88 of 184The Ring programming language version 1.5.3 book - Part 88 of 184
The Ring programming language version 1.5.3 book - Part 88 of 184
 
DjangoCon US 2011 - Monkeying around at New Relic
DjangoCon US 2011 - Monkeying around at New RelicDjangoCon US 2011 - Monkeying around at New Relic
DjangoCon US 2011 - Monkeying around at New Relic
 
Effective Modern C++ - Item 35 & 36
Effective Modern C++ - Item 35 & 36Effective Modern C++ - Item 35 & 36
Effective Modern C++ - Item 35 & 36
 
Threads, Queues, and More: Async Programming in iOS
Threads, Queues, and More: Async Programming in iOSThreads, Queues, and More: Async Programming in iOS
Threads, Queues, and More: Async Programming in iOS
 
Practical
PracticalPractical
Practical
 
The Ring programming language version 1.5.1 book - Part 75 of 180
The Ring programming language version 1.5.1 book - Part 75 of 180The Ring programming language version 1.5.1 book - Part 75 of 180
The Ring programming language version 1.5.1 book - Part 75 of 180
 
JVM Mechanics: Understanding the JIT's Tricks
JVM Mechanics: Understanding the JIT's TricksJVM Mechanics: Understanding the JIT's Tricks
JVM Mechanics: Understanding the JIT's Tricks
 
Ownership System in Rust
Ownership System in RustOwnership System in Rust
Ownership System in Rust
 
The Ring programming language version 1.9 book - Part 91 of 210
The Ring programming language version 1.9 book - Part 91 of 210The Ring programming language version 1.9 book - Part 91 of 210
The Ring programming language version 1.9 book - Part 91 of 210
 

Similar to Managing Mocks

Python testing using mock and pytest
Python testing using mock and pytestPython testing using mock and pytest
Python testing using mock and pytestSuraj Deshmukh
 
Mock it right! A beginner’s guide to world of tests and mocks, Maciej Polańczyk
Mock it right! A beginner’s guide to world of tests and mocks, Maciej PolańczykMock it right! A beginner’s guide to world of tests and mocks, Maciej Polańczyk
Mock it right! A beginner’s guide to world of tests and mocks, Maciej PolańczykPôle Systematic Paris-Region
 
Effective testing with pytest
Effective testing with pytestEffective testing with pytest
Effective testing with pytestHector Canto
 
Тестирование и Django
Тестирование и DjangoТестирование и Django
Тестирование и DjangoMoscowDjango
 
Solit 2013, Автоматизация тестирования сложных систем: mixed mode automated t...
Solit 2013, Автоматизация тестирования сложных систем: mixed mode automated t...Solit 2013, Автоматизация тестирования сложных систем: mixed mode automated t...
Solit 2013, Автоматизация тестирования сложных систем: mixed mode automated t...solit
 
Advanced Debugging Using Java Bytecodes
Advanced Debugging Using Java BytecodesAdvanced Debugging Using Java Bytecodes
Advanced Debugging Using Java BytecodesGanesh Samarthyam
 
Jdk 7 4-forkjoin
Jdk 7 4-forkjoinJdk 7 4-forkjoin
Jdk 7 4-forkjoinknight1128
 
Mocking in Java with Mockito
Mocking in Java with MockitoMocking in Java with Mockito
Mocking in Java with MockitoRichard Paul
 
Numerical tour in the Python eco-system: Python, NumPy, scikit-learn
Numerical tour in the Python eco-system: Python, NumPy, scikit-learnNumerical tour in the Python eco-system: Python, NumPy, scikit-learn
Numerical tour in the Python eco-system: Python, NumPy, scikit-learnArnaud Joly
 
Qualidade levada a sério em Python - Emilio Simoni
Qualidade levada a sério em Python - Emilio SimoniQualidade levada a sério em Python - Emilio Simoni
Qualidade levada a sério em Python - Emilio SimoniGrupo de Testes Carioca
 
Easymock Tutorial
Easymock TutorialEasymock Tutorial
Easymock TutorialSbin m
 
Parallel Processing with IPython
Parallel Processing with IPythonParallel Processing with IPython
Parallel Processing with IPythonEnthought, Inc.
 

Similar to Managing Mocks (20)

Python testing using mock and pytest
Python testing using mock and pytestPython testing using mock and pytest
Python testing using mock and pytest
 
Rhino Mocks
Rhino MocksRhino Mocks
Rhino Mocks
 
Mock it right! A beginner’s guide to world of tests and mocks, Maciej Polańczyk
Mock it right! A beginner’s guide to world of tests and mocks, Maciej PolańczykMock it right! A beginner’s guide to world of tests and mocks, Maciej Polańczyk
Mock it right! A beginner’s guide to world of tests and mocks, Maciej Polańczyk
 
Python testing
Python  testingPython  testing
Python testing
 
Easy mock
Easy mockEasy mock
Easy mock
 
Effective testing with pytest
Effective testing with pytestEffective testing with pytest
Effective testing with pytest
 
Easy mockppt
Easy mockpptEasy mockppt
Easy mockppt
 
Тестирование и Django
Тестирование и DjangoТестирование и Django
Тестирование и Django
 
Solit 2013, Автоматизация тестирования сложных систем: mixed mode automated t...
Solit 2013, Автоматизация тестирования сложных систем: mixed mode automated t...Solit 2013, Автоматизация тестирования сложных систем: mixed mode automated t...
Solit 2013, Автоматизация тестирования сложных систем: mixed mode automated t...
 
Advanced Debugging Using Java Bytecodes
Advanced Debugging Using Java BytecodesAdvanced Debugging Using Java Bytecodes
Advanced Debugging Using Java Bytecodes
 
Jdk 7 4-forkjoin
Jdk 7 4-forkjoinJdk 7 4-forkjoin
Jdk 7 4-forkjoin
 
Mocking in Java with Mockito
Mocking in Java with MockitoMocking in Java with Mockito
Mocking in Java with Mockito
 
Numerical tour in the Python eco-system: Python, NumPy, scikit-learn
Numerical tour in the Python eco-system: Python, NumPy, scikit-learnNumerical tour in the Python eco-system: Python, NumPy, scikit-learn
Numerical tour in the Python eco-system: Python, NumPy, scikit-learn
 
Qualidade levada a sério em Python - Emilio Simoni
Qualidade levada a sério em Python - Emilio SimoniQualidade levada a sério em Python - Emilio Simoni
Qualidade levada a sério em Python - Emilio Simoni
 
Django (Web Konferencia 2009)
Django (Web Konferencia 2009)Django (Web Konferencia 2009)
Django (Web Konferencia 2009)
 
Easymock Tutorial
Easymock TutorialEasymock Tutorial
Easymock Tutorial
 
Jersey Guice AOP
Jersey Guice AOPJersey Guice AOP
Jersey Guice AOP
 
Auto testing!
Auto testing!Auto testing!
Auto testing!
 
Android TDD
Android TDDAndroid TDD
Android TDD
 
Parallel Processing with IPython
Parallel Processing with IPythonParallel Processing with IPython
Parallel Processing with IPython
 

Recently uploaded

Diamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionDiamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionSolGuruz
 
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...harshavardhanraghave
 
Right Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsRight Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsJhone kinadey
 
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...MyIntelliSource, Inc.
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdfWave PLM
 
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...ICS
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVshikhaohhpro
 
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsAlberto González Trastoy
 
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...OnePlan Solutions
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...Health
 
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Steffen Staab
 
Hand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxHand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxbodapatigopi8531
 
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...MyIntelliSource, Inc.
 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Modelsaagamshah0812
 
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...kellynguyen01
 
CALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female service
CALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female serviceCALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female service
CALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female serviceanilsa9823
 
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfkalichargn70th171
 
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerHow To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerThousandEyes
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providermohitmore19
 

Recently uploaded (20)

Diamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionDiamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with Precision
 
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
 
Microsoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdfMicrosoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdf
 
Right Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsRight Money Management App For Your Financial Goals
Right Money Management App For Your Financial Goals
 
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf
 
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTV
 
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
 
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
 
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
 
Hand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxHand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptx
 
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Models
 
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
 
CALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female service
CALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female serviceCALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female service
CALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female service
 
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
 
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerHow To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service provider
 

Managing Mocks

  • 1. Managing mocks The how, why and when of mocking in Python Helen Sherwood-Taylor EuroPython 21st July 2016
  • 2. What is a mock? A fake object that replaces a real object Control and isolate the test's environment
  • 3. Why? Deterministic tests Control the test inputs Faster test suites
  • 4. unittest.mock >>> from unittest import mock # Or, for Python <3.3 $ pip install mock >>> import mock also known as the mock library written by Michael Foord Added to Python in 3.3 Rolling backport for earlier Pythons not just for unittest
  • 5. Mock objects >>> from unittest.mock import Mock >>> mock_talk = Mock(conference='EuroPython') >>> mock_talk.conference 'EuroPython' >>> mock_talk.speaker <Mock name='mock.speaker' id='139910592223552'> >>> mock_talk.speaker.name <Mock name='mock.speaker.name' id='139910592222208'> >>> mock_talk.speaker.name = 'Helen' >>> mock_talk.speaker.name 'Helen' Properties of Mocks
  • 6. Callable Mocks >>> mock_talk.speaker.get_twitter_status() <Mock name='mock.speaker.get_twitter_status()'> >>> mock_talk.speaker. get_twitter_status.return_value = 'Eating pintxos' >>> mock_talk.speaker.get_twitter_status() 'Eating pintxos' return_value
  • 7. Side effects An exception >>> mock_func = Mock() >>> mock_func.side_effect = ValueError >>> mock_func() Traceback (most recent call last): ... ValueError A function >>> mock_func.side_effect = lambda x: x*2 >>> mock_func(2) 4
  • 8. Multiple side effects A list of return values and exceptions >>> mock_func.side_effect = [1, ValueError, 2] >>> mock_func() Traceback (most recent call last): ... ValueError >>> mock_func() Traceback (most recent call last): ... StopIteration >>> mock_func() 1 >>> mock_func() 2
  • 9. What was called? assert_called_with(*args, **kwargs) assert_called_once_with(*args, **kwargs) assert_any_call(*args, **kwargs) assert_has_calls((call(*args, **kwargs), ...)) assert_not_called() >>> from unittest.mock import Mock, call >>> mock_func = Mock() >>> mock_func(1) >>> mock_func(2) >>> mock_func.assert_called_with(2) >>> mock_func.assert_has_calls([call(1), call(2)])
  • 10. Beware versions assert_not_called >>> mock_func = Mock() >>> mock_func() >>> mock_func.assert_not_called() <Mock name='mock.assert_not_called()' id='139758629541536'> python 3.5 >>> mock_func = Mock() >>> mock_func() >>> mock_func.assert_not_called() ... AssertionError: Expected 'mock' to not have been called. Called 1 times. python 3.4
  • 11. assert safety python 3.5 >>> from unittest.mock import Mock, call >>> mock_func = Mock() >>> mock_func.assert_called() ... AttributeError: assert_called Detects non existent assertion calls disable it with unsafe=True assert* assret*
  • 12. Matching call args mock.ANY doesn't care >>> from unittest.mock import Mock, ANY >>> mock_func = Mock() >>> mock_func(25) >>> mock_func.assert_called_with(ANY)
  • 13. Comparisons Use comparison objects for more control class MultipleMatcher: def __init__(self, factor): self.factor = factor def __eq__(self, other): return other % self.factor == 0 def __repr__(self): return 'Multiple of {}'.format(self.factor) >>> mock_func = Mock() >>> mock_func(25) >>> mock_func.assert_called_with(MultipleMatcher(5)) >>> mock_func.assert_called_with(MultipleMatcher(4)) ... AssertionError: Expected call: mock_func(Multiple of 4) Actual call: mock_func(25)
  • 14. Call inspection Lower level inspection of calls called - was it called? call_count - how many times? call_args - args/kwargs of last call call_args_list - args/kwargs of all calls
  • 15. How to use all this 1. Create / insert a mock 2. Set up inputs / environment 3. Run the code under test 4. Assert expectations met
  • 16. patch Get access to anything >>> from unittest.mock import patch >>> patch('requests.get') <unittest.mock._patch object at 0x7f7a2af03588> creates a MagicMock
  • 17. patch decorator import requests def get_followers(username): response = requests.get( 'https://api.github.com/users/%s' % username ) return response.json()['followers'] @patch('requests.get') def test_get_followers(mock_get): mock_get.return_value.json.return_value = {'followers': 100} assert get_followers('somebody') == 100 mock is a parameter to the test method >>> print(get_followers('helenst')) 25
  • 18. patch context manager with patch('requests.get') as mock_get: mock_get.return_value.json.return_value = {'followers': 100} assert get_followers('somebody') == 100
  • 19. patch: manual control patcher = patch('requests.get') mock_get = patcher.start() mock_get.return_value.json.return_value = {'followers': 100} assert get_followers('somebody') == 100 patcher.stop()
  • 20. Where to patch # github_utils.py import requests def get_followers(username): response = requests.get( 'https://api.github.com/users/%s' % username ) return response.json()['followers'] import github_utils with patch('requests.get') as mock_get: mock_get.return_value.json.return_value = {'followers': 100} # This will succeed. assert github_utils.get_followers('somebody') == 100
  • 21. Where to patch: 2 # file: github_utils2 from requests import get def get_followers(username): response = get( 'https://api.github.com/users/%s' % username ) return response.json()['followers'] import github_utils2 with patch('requests.get') as mock_get: mock_get.return_value.json.return_value = {'followers': 100} assert github_utils2.get_followers('somebody') == 100 AssertionError: 25 != 100
  • 22. Where to patch: the answer patch('github_utils2.get') import github_utils2 with patch('github_utils2.get') as mock_get: mock_get.return_value.json.return_value = {'followers': 100} # This will succeed. assert github_utils2.get_followers('somebody') == 100 Patch the imported path “ ensure that you patch the name used by the system under test.
  • 23. patch.object Attach mocks to an object class User: def is_birthday(self): # ... pass def greet(self): if self.is_birthday(): return 'happy birthday' else: return 'hello' user = User() with patch.object(user, 'is_birthday', return_value=True): # user.is_birthday is a MagicMock that returns True # Check the outcome assert user.greet() == 'happy birthday'
  • 24. Mock the time >>> patch("datetime.date.today").start() ... TypeError: can't set attributes of built-in/extension type 'datetime.date' date is written in C so you can't mock its attributes. >>> patch('datetime.date').start() <MagicMock name='date' id='140222796874696'> But you can mock the whole thing.
  • 25. Is it my birthday? from datetime import date def its_my_birthday(): today = date.today() return today.month == 3 and today.day == 19 import birthday @patch('birthday.date') def test_birthday_3(mock_date): mock_date.today.return_value = date(2016, 3, 19) assert birthday.its_my_birthday()
  • 26. freezegun $ pip install freezegun from freezegun import freeze_time import birthday @freeze_time('2016-03-19') def test_birthday_4(): assert birthday.its_my_birthday()
  • 27. Mock the filesystem from unittest.mock import mock_open open_mock = mock_open( read_data='look at all my file contents' ) with patch('__main__.open', open_mock, create=True): with open('myfile') as file: assert file.read() == 'look at all my file contents' mock_open will help you out here. But you can't iterate
  • 28. Iterate a mock file with patch('__main__.open', mock_open(), create=True) as open_mock: mock_file = open_mock.return_value.__enter__.return_value mock_file.__iter__.return_value = ([ 'line one', 'line two' ]) with open('myfile') as file: assert list(file) == ['line one', 'line two'] with open('myfile') as myfile: for line in myfile: print(line)
  • 29. Mock a property class Person: @property def is_birthday(self): today = date.today() return self.dob.month == today.month and self.dob.day == today.day def greet(self): return 'Happy birthday!' if self.is_birthday else 'Good morning!' # Patching the object doesn't work. >>> with patch.object(person, 'is_birthday', return_value=True): ... assert person.greet() == 'Happy birthday!' ... AttributeError: <__main__.Person object at 0x7f9875ea73c8> does not have the attribute 'is_birthday'
  • 30. How to mock a property with patch.object( Person, 'is_birthday', new_callable=PropertyMock, return_value=True ): assert person.greet() == 'Happy birthday!' use new_callable patch the class
  • 31. Example: delay loop def retry_with_delay(func): delay = 1 while True: try: return func() except DatabaseError: time.sleep(delay) delay *= 2 @patch('time.sleep') def test_third_time_lucky(mock_sleep): mock_func = Mock(side_effect=[DatabaseError, DatabaseError, 'Yay']) result = retry_with_delay(mock_func) assert mock_func.call_count == 3 mock_sleep.assert_has_calls([ call(1), call(2), ]) assert result == 'Yay'
  • 32. When to mock? Current time say happy birthday to a user Simulated failure (what happens when the disk is full?) Slowness e.g. time.sleep Randomness Remote APIs any data you want
  • 33. What about the rest? Purity / Design Speed Pinpoint failures Realistic coverage Harder to read Harder to write Meaningless? Doesn't test inter-layer stuff Should I mock the other layers? YES NO
  • 34. Further reading Book: http://www.obeythetestinggoat.com/ Talk: Gary Bernhardt - Fast Test, Slow Test https://docs.python.org/3/library/unittest.mock.html
  • 35. Thank you! Twitter: @helenst Github: @helenst http://helen.st/ https://github.com/helenst/managing_mocks