20081024 practical python unit testing wuchengli

12
Google Confidential and Proprietary 1 Practical Python Unit Testing Wu-cheng Li Oct 24, 2008

Upload: foolsworkish

Post on 27-Apr-2017

226 views

Category:

Documents


4 download

TRANSCRIPT

Google Confidential and Proprietary 1

Practical Python Unit Testing

Wu-cheng LiOct 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