Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Python, what's a good pattern for disabling certain code during unit tests?

In general I want to disable as little code as possible, and I want it to be explicit: I don't want the code being tested to decide whether it's a test or not, I want the test to tell that code "hey, BTW, I'm running a unit test, can you please not make your call to solr, instead can you please stick what you would send to solr in this spot so I can check it". I have my ideas but I don't like any of them, I am hoping that there's a good pythonic way to do this.

like image 717
guidoism Avatar asked Feb 23 '10 17:02

guidoism


2 Answers

You can use Mock objects to intercept the method calls that you do not want to execute. E.g. You have some class A, where you don't want method no() to be called during a test.

class A:
  def do(self):
    print('do')
  def no(self):
    print('no')

A mock object could inherit from A and override no() to do nothing.

class MockA(A):
  def no(self):
    pass

You would then create MockA objects instead of As in your test code. Another way to do mocking would be to have A and MockA implement a common interface say InterfaceA.

There are tons of mocking frameworks available. See StackOverflow: Python mocking frameworks.

In particular see: Google's Python mocking framework.

like image 83
Pierre-Antoine LaFayette Avatar answered Sep 28 '22 03:09

Pierre-Antoine LaFayette


Use Michael Foord's Mock in your unit test do this:

from mock import Mock

class Person(object):
    def __init__(self, name):
        super(Person, self).__init__()
        self.name = name

    def say(self, str):
        print "%s says \"%s\"" % (self.name, str)


...

#In your unit test....
#create the class as normal
person = Person("Bob")
#now mock all of person's methods/attributes
person = Mock(spec=person)
#talkto is some function you are testing
talkTo(person)
#make sure the Person class's say method was called
self.assertTrue(person.say.called, "Person wasn't asked to talk")

#make sure the person said "Hello"
args = ("Hello")
keywargs = {}
self.assertEquals(person.say.call_args, (args, keywargs), "Person did not say hello")
like image 45
manifest Avatar answered Sep 28 '22 02:09

manifest