A Brainstorm Before Starting
A Brainstorm before starting¶
Taken from: Julien Danjou's Hacker's Guide To Python
import this
import sys
sys.builtin_module_names
from itertools import permutations
print(sum(1 for _ in permutations([1, 2, 3, 4, 5])))
"Whenever you are about to write our own function to handle a simple task, please stop and look through the standard library first."
"There’s a few of the standard modules that you should definitely know about:
- operator: provides functions implementing the basic Python operators which you can use instead of having t owrite your own lambda expressions
- os: provides access to basic OS functions.
- random: provides functions for generating pseudo-random numbers.
- re: provides regular expression functionalities.
- functools
- iterators
- uuid: allows to autogenerate UUIDs(Universall Unique Identifiers)."
## Unittest setUp() and tearDown(). Running code before and after unittest
import unittest
class TestMe(unittest.TestCase):
def setUp(self):
self.list = [1, 2, 3]
def test_length(self):
self.list.append(4)
self.assertEqual(len(self.list), 4)
def test_has_one(self):
self.assertEqual(len(self.list), 3)
self.assertIn(1, self.list)
fixtures module¶
"The fixtures module provides a few built-in fixtures, like fixtures.Environment Variable – useful for adding or changing a variable in os.environ that will be reset upon test exit."
import fixtures # not part of the standard library
import os
class TestEnviron(fixtures.TestWithFixtures): # inherits from unittest TestCase
def test_environ(self):
fixture = self.useFixture(fixtures.EnvironmentVariable("FOOBAR", "42"))
self.assertEqual(os.environ.get("FOOBAR"), "42")
def test_environ_no_fixture(self):
self.assertEqual(os.environ.get("FOOBAR"), None)
Mocking¶
"Mock objects are simulated objects that mimic the behaviour of real application objects, but in particular and controlled ways. These are especially useful in creating environments that describe precisely the conditions for which you would like to testcode"
from unittest import mock
m = mock.Mock()
m.some_method.return_value = 42
print(m.some_method())
def print_hello():
print("hello world!")
return 43
m.some_method.side_effect = print_hello
print(m.some_method())
m.some_method.call_count # stats on method calling
Example: Using mock.patch to test a set of behaviour
import requests
import unittest
import mock
class WhereIsPythonError(Exception):
pass
def is_python_still_a_programming_language():
try:
r = requests.get("http://python.org")
except IOError:
pass
else:
if r.status_code == 200:
return 'Python is a programming language' in r.content
raise WhereIsPythonError("Something bad happened")
def get_fake_get(status_code, content):
m = mock.Mock()
m.status_code = status_code
m.content = content
def fake_get(url):
return m
return fake_get
def raise_get(url):
raise IOError("Unable to fetch url %s" % url)
class TestPython(unittest.TestCase):
@mock.patch('requests.get', get_fake_get(200, 'Python is a programming language for sure'))
def test_python_is(self):
self.assertTrue(is_python_still_a_programming_language())
@mock.patch('requests.get', get_fake_get( 200, 'Python is no more a programming language'))
def test_python_is_not(self):
self.assertFalse(is_python_still_a_programming_language())
@mock.patch('requests.get', get_fake_get( 404, 'Whatever'))
def test_bad_status_code(self):
self.assertRaises(WhereIsPythonError, is_python_still_a_programming_language)
@mock.patch('requests.get', raise_get)
def test_ioerror(self):
self.assertRaises(WhereIsPythonError, is_python_still_a_programming_language)
Scenarios¶
"This package provides an easy way to run a class test against a different set of scenarios generated at run-time." Same example as in Mocking, the test runs three times because three scenarios are defined:
import mock
import requests
import testscenarios
class WhereIsPythonError(Exception):
pass
def is_python_still_a_programming_language():
r = requests.get("http://python.org")
if r.status_code == 200:
return 'Python is a programming language' in r.content
raise WhereIsPythonError("Something bad happened")
def get_fake_get(status_code, content):
m = mock.Mock()
m.status_code = status_code
m.content = content
def fake_get(url):
return m
return fake_get
class TestPythonErrorCode(testscenarios.TestWithScenarios):
scenarios = [ ('Not found', dict(status=404)),
('Client error', dict(status=400)),
('Server error', dict(status=500)), ]
def test_python_status_code_handling(self):
with mock.patch('requests.get', get_fake_get( self.status, 'Python is a programming language for sure')):
self.assertRaises(WhereIsPythonError, is_python_still_a_programming_language)
Profiling¶
import cProfile
import time
def print_hello():
def print_it():
for _ in range(0, 5):
time.sleep(0.2)
print('here')
print("hello world!")
print_it()
return 43
cProfile.run('print_hello()')
Disassemble¶
import dis
dis.dis(lambda x, y: sqrt(x ** 2 + y ** 2))
Memory allocation¶
A variable and its name have the same address in RAM.
a = 2
print(id(2))
id(a)
a = 2
id(a)
>> 507098816
a = a+1
id(a)
>>> 507098848
id(3)
>>> 507098848 # 3 and the a+1=2 have the same address
b = 2
id(b)
>>> 507098816 # b has value 2, so it has the same address as a
### http://www.programiz.com/python-programming/namespace
This dynamic nature of name binding makes Python powerful.