Sunteți pe pagina 1din 12

Google Confidential and Proprietary 1

Practical Python Unit Testing


Wu-cheng Li
Oct 24, 2008
Google Confidential and Proprietary
Outlines
googletest.StubOutForTesting
lambda
googletest.DoNothing
Mox Revisited
Advanced Mox
InAnyOrder & MultipleTimes
Comparators
With Side Effects
(StubOutWithMock)
(CreateMockAnything)
2
Google Confidential and Proprietary
googletest.StubOutForTesting
Use StubOutForTesting to stub a function or method.
3
class ShoppingCartTest(googletest.TestCase):
def setUp(self):
self.stubs = googletest.StubOutForTesting()
self.stubs.Set(os.path, exists, MyExist)

def tearDown(self):
self.stubs.UnsetAll()
stubs.Set(os.path, exists, lambda x: 1)
stubs.Set(thread_pool, 'ThreadPool', googletest.DoNothing)
stubs.Set(mock_rpc, CreateTopic, lambda *_, **unused: id12345)
stubs.Set(BaseHTTPServer.HTTPServer, '__init__', lambda x,y,z: None)
Google Confidential and Proprietary
googletest.StubOutForTesting
Implementation of StubOutForTesting
4
class StubOutForTesting(object):
def Set(self, parent, child_name, new_child):
old_child = getattr(parent, child_name)
old_attribute = parent.__dict__.get(child_name)

if old_attribute is not None and isinstance(old_attribute, staticmethod):
old_child = staticmethod(old_child)
self.cache.append((parent, old_child, child_name))
setattr(parent, child_name, new_child)
class DoNothing(object):
def __init__(self, *args, **kwargs):
pass

def __getattr__(self, unused_name):
return lambda *args, **kwargs: 1
Google Confidential and Proprietary
Mox Revisited
Mox is a mock object framework for Python.
Flow
Record -> Setup expectations -> Reply -> Run test -> Verify
5
class ShoppingCartTest(googletest.TestCase):
def testCalculateTax(self):
m = mox.Mox()
mock = m.CreateMock(ShoppingCart)
mock.OpenConnection()
mock.GetTax(85018).AndReturn(8)
mock.GetPrice(None).AndRaise(AssertionError)
m.ReplayAll()

cart = ShoppingCart(mock)
cart.GetTax(85018)
self.assertEquals(8, tax)
self.assertRaises(AssertionError, cart, GetPrice,
None)
m.VerifyAll()
class ShoppingCart:
def __init__(self, server):
self.server = server
server.OpenConnection()

def GetTax(self, zipcode):
rate = server.GetTaxRate(zipcode)
return rate

def GetPrice(self, id):
price = server.GetPrice(id)
return price
Google Confidential and Proprietary
Advanced Mox InAnyOrder & MultipleTimes
dao.OpenConnection()
dao.Call(1).InAnyOrder().AndReturn('one')
dao.Call(2).InAnyOrder().AndReturn('two')
dao.Call(3).InAnyOrder().AndReturn('three')
dao.CloseConnection()
mox.Replay(mock)
6
dao.OpenConnection()
dao.Foo(1).MultipleTimes().AndReturn('one')
dao.Foo(2).MultipleTimes().AndReturn('two')
dao.Foo(3).MultipleTimes().AndReturn('three')
mox.Replay(mock)
Google Confidential and Proprietary
Advanced Mox - Comparators
dao.UpdateUser(3, IgnoreArg(), 'admin')
dao.InsertAuditRecord(Func(IsValidAudit))
dao.InsertUser(IsA(Person))
dao.RunSql(StrContains('WHERE id=%d' % expected_id))
dao.RunSql(Regex(r'WHERE.*\s+id=%d' % expected_id))
dao.BulkInsert(In(test_person))
dao.BulkInsert(ContainsKeyValue(test_id, test_person))
dao.AddInterestToAccount(IsAlmost(0.05))
dao.ProcessUsers(SameElementsAs([person1, person2]))
dao.BulkInsert(And(In(test_person), IsA(list))
7
Google Confidential and Proprietary
Advanced Mox With Side Effects
def add_msgs(msg_list):
msg_list += ['msg1', 'msg2']

msg_appender = mox.MockObject(PendingMsgs)
msg_appender.GetWaitingMessages(['msg0]).WithSideEffects(
add_msgs).AndReturn(2)
mox.Replay(msg_appender)

msgs = ['msg0']
new_msgs = msg_appender.GetWaitingMessages(msgs)
mox.Verify(msg_appender)
assertEquals(['msg0', 'msg1', 'msg2'], msgs)
8
Google Confidential and Proprietary
Advanced Mox StubOutWithMock
Code to be tested
class MyRequestHandler(object):
def HandleRequest(self, request):
if request.IsExternal():
self.Authenticate(request)
self.Authorize(request)
self.Process(request)
else:
self.ProcessInternal(request)
Unittest
handler = MyRequestHandler()
m = mox.Mox()
m.StubOutWithMock(handler, "Authenticate")
m.StubOutWithMock(handler, "Authorize")
m.StubOutWithMock(handler, "Process")
handler.Authenticate(IsA(Request))
handler.Authorize(IsA(Request))
handler.Process(IsA(Request))
m.ReplayAll()

handler.HandleRequest(request)

m.UnsetStubs()
m.VerifyAll()
9
Google Confidential and Proprietary
Advanced Mox CreateMockAnything
m = mox.Mox()
mock_rpc = m.CreateMockAnything()
mock_rpc.CreateUser()
m = mox.Mox()
mock_rpc = m.CreateMock(RpcClass)
mock_rpc.CreateUser()



10
Google Confidential and Proprietary
MockMethod
Implementation of MockMethod
11
class MockMethod(object):
def __call__(self, *params, **named_params):
self._params = params
self._named_params = named_params
if not self._replay_mode:
self._call_queue.append(self)
return self

expected_method = self._VerifyMethodCall()
if expected_method._side_effects:
expected_method._side_effects(*params, **named_params)
if expected_method._exception:
raise expected_method._exception

return expected_method._return_value
Google Confidential and Proprietary 12
Thank You!
Q&A

S-ar putea să vă placă și