unittest help

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Qiangning Hong

    #1

    unittest help

    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(s elf.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(uni ttest.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?)

  • André Malo

    #2
    Re: unittest help

    * "Qiangning Hong" <hongqn@gmail.c om> wrote:
    [color=blue]
    > 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(s elf.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?[/color]

    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._loadExtmo d()
    self.handle = self._extmod.op en()

    def __del__(self):
    self._extmod.cl ose(self.handle )

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

    def some_stuff(self ):
    self._extmod.fo obar(self.handl e)

    Now just overload _loadExtmod and provide the mock class there.

    HTH, nd

    Comment

    • Duncan Booth

      #3
      Re: unittest help

      Qiangning Hong wrote:
      [color=blue]
      > 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(uni ttest.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?)
      >[/color]

      One way is simply to do:

      def setUp(self):
      import myclass
      self.real_extmo d = myclass._extmod
      myclass._extmod = mocklib.MockExt Mod()
      self.testobj = myclass.MyClass ()

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

      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.

      Comment

      • Scott David Daniels

        #4
        Re: unittest help

        Duncan Booth wrote:[color=blue]
        > Qiangning Hong wrote:
        >
        >[color=green]
        >>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:[/color][/color]

        Given:[color=blue][color=green]
        >> # file: myclass.py
        >> import _extmod
        >> class MyClass(object) :
        >> def __init__(self):
        >> self.handle = _extmod.open()
        >> ...[/color][/color]

        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(u nittest.TestCas e):
        ...

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

        --Scott David Daniels
        Scott.Daniels@A cm.Org

        Comment

        Working...