unittest help

Q

Qiangning Hong

I want to apply TDD (test driven development) on my project. I am
working on a class like this (in plan):

# file: myclass.py
import _extmod

class MyClass(object):
def __init__(self):
self.handle = _extmod.open()

def __del__(self):
_extmod.close(self.handle)

def some_stuff(self):
_extmod.foobar(self.handle)

...

As you see, it is an OO wrapper on _extmod, which is a pyrex extension
module. The question is: how to unittest this class? As the _extmod
is hardware-dependent, I want to use a mock class to replace it in unit
test. But how can I let myclass in unittest to import the mock class?
Like the following:

class MyClassTest(unittest.TestCase):
def setUp(self):
import myclass
import mocklib
myclass.change_extmod(mocklib.MockExtMod())
self.testobj = myclass.MyClass() # here MyClass.__init__ will
call the open
# method of MockExtMod class
instead of
# _extmod.open()
...

How to implement the change_extmod? (Or maybe my idea is totally
wrong?)
 
?

=?ISO-8859-1?Q?Andr=E9?= Malo

* "Qiangning Hong said:
I want to apply TDD (test driven development) on my project. I am
working on a class like this (in plan):

# file: myclass.py
import _extmod

class MyClass(object):
def __init__(self):
self.handle = _extmod.open()

def __del__(self):
_extmod.close(self.handle)

def some_stuff(self):
_extmod.foobar(self.handle)

...

As you see, it is an OO wrapper on _extmod, which is a pyrex extension
module. The question is: how to unittest this class? As the _extmod
is hardware-dependent, I want to use a mock class to replace it in unit
test. But how can I let myclass in unittest to import the mock class?

You need to design for testability, meaning in this case, that your class could
to do something like this:

class MyClass(object):
def __init__(self):
self._loadExtmod()
self.handle = self._extmod.open()

def __del__(self):
self._extmod.close(self.handle)

def _loadExtmod(self):
import _extmod
self._extmod = extmod

def some_stuff(self):
self._extmod.foobar(self.handle)

Now just overload _loadExtmod and provide the mock class there.

HTH, nd
 
D

Duncan Booth

Qiangning said:
As you see, it is an OO wrapper on _extmod, which is a pyrex extension
module. The question is: how to unittest this class? As the _extmod
is hardware-dependent, I want to use a mock class to replace it in unit
test. But how can I let myclass in unittest to import the mock class?
Like the following:

class MyClassTest(unittest.TestCase):
def setUp(self):
import myclass
import mocklib
myclass.change_extmod(mocklib.MockExtMod())
self.testobj = myclass.MyClass() # here MyClass.__init__ will
call the open
# method of MockExtMod class
instead of
# _extmod.open()
...

How to implement the change_extmod? (Or maybe my idea is totally
wrong?)

One way is simply to do:

def setUp(self):
import myclass
self.real_extmod = myclass._extmod
myclass._extmod = mocklib.MockExtMod()
self.testobj = myclass.MyClass()

def tearDown(self):
import myclass
if hasattr(self, testobj):
del self.testobj
myclass._extmod = self.real_extmod

This can be less intrusive than passing the mock object to a constructor,
but it depends very much on the way the objects are used: changing global
state for a unit test is a risky business, for example if an exception is
thrown then tearDown would be called *before* your __del__ method is
invoked. You can work round this by ensuring that the _extmod value is
saved in your instance but that takes you pretty much back to André Malo's
suggestion.

BTW, accessing a global variable from a __del__ method is a bad idea
generally: there is no guarantee that the global variable will still be set
if __del__ is called during program exit.
 
S

Scott David Daniels

Duncan said:
Qiangning Hong wrote:


Given:

One other way to do your unit test stuff is:
# file: test_myclass.py

import sys, bogus_extmod # First, get the fake hardware
sys.modules['_extmod'] = bogus_extmod # then make that active

import myclass, unittest # and now do all you normally would do
...
class SimplestTests(unittest.TestCase):
...

Note that the "module switch" must happen very early (probably at
the top of the main program).

--Scott David Daniels
(e-mail address removed)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,766
Messages
2,569,569
Members
45,043
Latest member
CannalabsCBDReview

Latest Threads

Top