Unit Testing and sending events

I love writing unit tests (I'm not sure why it's just something I find
quite enjoyable). I don't think I have quite 100% code coverage for
the engine of my current toy project, but it is likely very close (I
try not to write any code unless I have a test to prove I need it).

Unfortunately that is NOT the case with the GUI part of my code. I
made some initial attempts, wasn't happy with the results, and had too
many ideas running around in my head that I needed to get into code so
the GUI code (until this morning) was completely untested.

This morning I buckled down and started messing around a bit with unit
tests for the GUI. So far it's been a mixed bag.

My tiny little App() class sets the wx.ToolTip.Delay(), but as far as
I know there is no way to prove that I actually set the ToolTip delay
in a unit test. My biggest hurdle is sending events to objects.

I have a Notebook object and so far my attempts at creating a
CommandEvent or a NotebookEvent and then passing it to the
ProcessEvent() method of the object have failed. I usually end up with
an error stating "expected argument of type wxEventType.

I'm at a loss. Can anyone point me in the right direction?

···

--
Stand Fast,
tjg. [Timothy Grant]

Hi Timothy,

···

2008/8/3 Timothy Grant <timothy.grant@gmail.com>:

I have a Notebook object and so far my attempts at creating a
CommandEvent or a NotebookEvent and then passing it to the
ProcessEvent() method of the object have failed. I usually end up with
an error stating "expected argument of type wxEventType.

I'm at a loss. Can anyone point me in the right direction?

I usually don't bother to create the event, but just call the event
handler with a dummy event (using duck typing). The only thing not
tested then is that clicking the button (or whatever) is actually
bound to the event handler, but that is verified by hand easily and
not a very common mistake in my experience.

Cheers, Frank

It is possible also to declare the event handler so:
def EventHandler(self, event = None):

···

2008/8/3 Frank Niessink frank@niessink.com

Hi Timothy,

2008/8/3 Timothy Grant timothy.grant@gmail.com:

I have a Notebook object and so far my attempts at creating a

CommandEvent or a NotebookEvent and then passing it to the

ProcessEvent() method of the object have failed. I usually end up with

an error stating "expected argument of type wxEventType.

I’m at a loss. Can anyone point me in the right direction?

I usually don’t bother to create the event, but just call the event

handler with a dummy event (using duck typing). The only thing not

tested then is that clicking the button (or whatever) is actually

bound to the event handler, but that is verified by hand easily and

not a very common mistake in my experience.

Cheers, Frank


wxpython-users mailing list

wxpython-users@lists.wxwidgets.org

http://lists.wxwidgets.org/mailman/listinfo/wxpython-users

Thank you very much Frank.

Incredibly helpful advice.

I was starting to get frustrated because I had no way to prove my GUI
was acting as expected or that other changes weren't breaking things
that previously worked.

I'll be really glad to get that code tested.

···

On Sun, Aug 3, 2008 at 1:47 PM, Frank Niessink <frank@niessink.com> wrote:

Hi Timothy,

2008/8/3 Timothy Grant <timothy.grant@gmail.com>:

I have a Notebook object and so far my attempts at creating a
CommandEvent or a NotebookEvent and then passing it to the
ProcessEvent() method of the object have failed. I usually end up with
an error stating "expected argument of type wxEventType.

I'm at a loss. Can anyone point me in the right direction?

I usually don't bother to create the event, but just call the event
handler with a dummy event (using duck typing). The only thing not
tested then is that clicking the button (or whatever) is actually
bound to the event handler, but that is verified by hand easily and
not a very common mistake in my experience.

Cheers, Frank

--
Stand Fast,
tjg. [Timothy Grant]

Thanks Raffaello.

I use that construct quite often. Unfortunately from a unit test
standpoint, I more often need data from the event class than not.

···

On Sun, Aug 3, 2008 at 2:38 PM, raffaello <barbarossa.platz@gmail.com> wrote:

It is possible also to declare the event handler so:
   def EventHandler(self, event = None):

2008/8/3 Frank Niessink <frank@niessink.com>

Hi Timothy,

2008/8/3 Timothy Grant <timothy.grant@gmail.com>:
> I have a Notebook object and so far my attempts at creating a
> CommandEvent or a NotebookEvent and then passing it to the
> ProcessEvent() method of the object have failed. I usually end up with
> an error stating "expected argument of type wxEventType.
>
> I'm at a loss. Can anyone point me in the right direction?

I usually don't bother to create the event, but just call the event
handler with a dummy event (using duck typing). The only thing not
tested then is that clicking the button (or whatever) is actually
bound to the event handler, but that is verified by hand easily and
not a very common mistake in my experience.

Cheers, Frank
_______________________________________________
wxpython-users mailing list
wxpython-users@lists.wxwidgets.org
http://lists.wxwidgets.org/mailman/listinfo/wxpython-users

_______________________________________________
wxpython-users mailing list
wxpython-users@lists.wxwidgets.org
http://lists.wxwidgets.org/mailman/listinfo/wxpython-users

--
Stand Fast,
tjg. [Timothy Grant]

Hi,

Could you elaborate on the duck typing?

How do you exactly create the dummy event?

/Chris

···

On Sun, Aug 3, 2008 at 10:47 PM, Frank Niessink <frank@niessink.com> wrote:

I usually don't bother to create the event, but just call the event
handler with a dummy event (using duck typing). The only thing not
tested then is that clicking the button (or whatever) is actually
bound to the event handler, but that is verified by hand easily and
not a very common mistake in my experience.

Christoffer Sørensen wrote:

Could you elaborate on the duck typing?

Basically it means to make an object look like it is an instance of some class, simply by implementing the methods of that class that will be needed in the context where it is used.

···

--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!

Hi Christoffer,

Could you elaborate on the duck typing?

How do you exactly create the dummy event?

Here's an actual example from Task Coach:

class DummyEvent(object):
    def __init__(self, selection=0):
        self.__selection = selection

    def GetSelection(self):
        return self.__selection

    Selection = property(GetSelection)

    def Skip(self):
        pass

This is used to test the behaviour of a 'ViewerContainer'
(self.container below) which can an AUI Notebook or a AUI Managed
Frame:

    def testChangePage_ChangesActiveViewer(self):
        self.container.onPageChanged(DummyEvent(1))
        self.assertEqual(self.viewer2, self.container.activeViewer())

    def testChangePage_SavesActiveViewerInSettings(self):
        self.container.onPageChanged(DummyEvent(1))
        self.assertEqual(1, self.settings.getint('view', 'mainviewer'))

    def testChangePage_NotifiesObserversAboutNewActiveViewer(self):
        patterns.Publisher().registerObserver(self.onEvent,
            eventType=self.container.viewerChangeEventType())
        self.container.onPageChanged(DummyEvent(1))
        self.failUnless(self.events)

    def testCloseViewer_RemovesViewerFromContainer(self):
        self.container.onPageClosed(DummyEvent())
        self.assertEqual([self.viewer2], self.container.viewers)

    def testCloseViewer_RemovesViewerFromSettings(self):
        self.container.onPageClosed(DummyEvent())
        self.assertEqual(1, self.settings.getint('view',
            'viewerwithdummywidgetcount'))

    def testCloseViewer_ChangesActiveViewer(self):
        self.container.onPageChanged(DummyEvent(1))
        self.container.onPageClosed(DummyEvent())
        self.assertEqual(self.viewer2, self.container.activeViewer())

Cheers, Frank

···

2008/8/4 Christoffer Sørensen <sorensen.christoffer@gmail.com>:

So I've been working on the whole duck typing and mock objects thing
with some success, but I would still love to be able to be able to
test a few "mouse-clicks." Because I thought it would be simple I
wrote the following test...

    def test__MainFrame__change_pages(self):
        mf = rollem.MainFrame(None)
        event =
wx.NotebookEvent(commandType=wx.wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED,
nSel=1)
        # event.SetSelection(1)
        mf.character_nb.ProcessEvent(event)
        assert mf.character_nb.GetCurrentPage().GetLabel() == 'Skills'

It always fails because the CurrentPage never changes from Page0. I
have tried explicitly setting the page involved with the commented-out
SetSelection() but that fails too.

I'm sure there's something simple that I am missing, but I am not sure
what it might be.

···

On Mon, Aug 4, 2008 at 12:14 PM, Frank Niessink <frank@niessink.com> wrote:

Hi Christoffer,

2008/8/4 Christoffer Sørensen <sorensen.christoffer@gmail.com>:

Could you elaborate on the duck typing?

How do you exactly create the dummy event?

Here's an actual example from Task Coach:

class DummyEvent(object):
   def __init__(self, selection=0):
       self.__selection = selection

   def GetSelection(self):
       return self.__selection

   Selection = property(GetSelection)

   def Skip(self):
       pass

This is used to test the behaviour of a 'ViewerContainer'
(self.container below) which can an AUI Notebook or a AUI Managed
Frame:

   def testChangePage_ChangesActiveViewer(self):
       self.container.onPageChanged(DummyEvent(1))
       self.assertEqual(self.viewer2, self.container.activeViewer())

   def testChangePage_SavesActiveViewerInSettings(self):
       self.container.onPageChanged(DummyEvent(1))
       self.assertEqual(1, self.settings.getint('view', 'mainviewer'))

   def testChangePage_NotifiesObserversAboutNewActiveViewer(self):
       patterns.Publisher().registerObserver(self.onEvent,
           eventType=self.container.viewerChangeEventType())
       self.container.onPageChanged(DummyEvent(1))
       self.failUnless(self.events)

   def testCloseViewer_RemovesViewerFromContainer(self):
       self.container.onPageClosed(DummyEvent())
       self.assertEqual([self.viewer2], self.container.viewers)

   def testCloseViewer_RemovesViewerFromSettings(self):
       self.container.onPageClosed(DummyEvent())
       self.assertEqual(1, self.settings.getint('view',
           'viewerwithdummywidgetcount'))

   def testCloseViewer_ChangesActiveViewer(self):
       self.container.onPageChanged(DummyEvent(1))
       self.container.onPageClosed(DummyEvent())
       self.assertEqual(self.viewer2, self.container.activeViewer())

Cheers, Frank

--
Stand Fast,
tjg. [Timothy Grant]

Timothy Grant wrote:

Hi Christoffer,

Could you elaborate on the duck typing?

How do you exactly create the dummy event?

Here's an actual example from Task Coach:

class DummyEvent(object):
   def __init__(self, selection=0):
       self.__selection = selection

   def GetSelection(self):
       return self.__selection

   Selection = property(GetSelection)

   def Skip(self):
       pass

This is used to test the behaviour of a 'ViewerContainer'
(self.container below) which can an AUI Notebook or a AUI Managed
Frame:

   def testChangePage_ChangesActiveViewer(self):
       self.container.onPageChanged(DummyEvent(1))
       self.assertEqual(self.viewer2, self.container.activeViewer())

   def testChangePage_SavesActiveViewerInSettings(self):
       self.container.onPageChanged(DummyEvent(1))
       self.assertEqual(1, self.settings.getint('view', 'mainviewer'))

   def testChangePage_NotifiesObserversAboutNewActiveViewer(self):
       patterns.Publisher().registerObserver(self.onEvent,
           eventType=self.container.viewerChangeEventType())
       self.container.onPageChanged(DummyEvent(1))
       self.failUnless(self.events)

   def testCloseViewer_RemovesViewerFromContainer(self):
       self.container.onPageClosed(DummyEvent())
       self.assertEqual([self.viewer2], self.container.viewers)

   def testCloseViewer_RemovesViewerFromSettings(self):
       self.container.onPageClosed(DummyEvent())
       self.assertEqual(1, self.settings.getint('view',
           'viewerwithdummywidgetcount'))

   def testCloseViewer_ChangesActiveViewer(self):
       self.container.onPageChanged(DummyEvent(1))
       self.container.onPageClosed(DummyEvent())
       self.assertEqual(self.viewer2, self.container.activeViewer())

Cheers, Frank

So I've been working on the whole duck typing and mock objects thing
with some success, but I would still love to be able to be able to
test a few "mouse-clicks." Because I thought it would be simple I
wrote the following test...

    def test__MainFrame__change_pages(self):
        mf = rollem.MainFrame(None)
        event =
wx.NotebookEvent(commandType=wx.wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED,
nSel=1)
        # event.SetSelection(1)
        mf.character_nb.ProcessEvent(event)
        assert mf.character_nb.GetCurrentPage().GetLabel() == 'Skills'

It always fails because the CurrentPage never changes from Page0. I
have tried explicitly setting the page involved with the commented-out
SetSelection() but that fails too.

I'm sure there's something simple that I am missing, but I am not sure
what it might be.

In most cases the sending of an event doesn't cause the thing to happen in the native widget, it is just notifying the program that it did happen. So to do what you intend with the code above you would actually have to synthesize a native mouse press event, followed by a native mouse release and then wait for the native widget to catch those events, process them and then finally do the work to change the selected page. Unfortunately the native event synthesis is not something that we can do yet from wx.

···

On Mon, Aug 4, 2008 at 12:14 PM, Frank Niessink <frank@niessink.com> wrote:

2008/8/4 Christoffer Sørensen <sorensen.christoffer@gmail.com>:

--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!

Well then, I think I shall be skipping that step!

···

On Wed, Aug 6, 2008 at 3:10 PM, Robin Dunn <robin@alldunn.com> wrote:

Timothy Grant wrote:

On Mon, Aug 4, 2008 at 12:14 PM, Frank Niessink <frank@niessink.com> >> wrote:

Hi Christoffer,

2008/8/4 Christoffer Sørensen <sorensen.christoffer@gmail.com>:

Could you elaborate on the duck typing?

How do you exactly create the dummy event?

Here's an actual example from Task Coach:

class DummyEvent(object):
  def __init__(self, selection=0):
      self.__selection = selection

  def GetSelection(self):
      return self.__selection

  Selection = property(GetSelection)

  def Skip(self):
      pass

This is used to test the behaviour of a 'ViewerContainer'
(self.container below) which can an AUI Notebook or a AUI Managed
Frame:

  def testChangePage_ChangesActiveViewer(self):
      self.container.onPageChanged(DummyEvent(1))
      self.assertEqual(self.viewer2, self.container.activeViewer())

  def testChangePage_SavesActiveViewerInSettings(self):
      self.container.onPageChanged(DummyEvent(1))
      self.assertEqual(1, self.settings.getint('view', 'mainviewer'))

  def testChangePage_NotifiesObserversAboutNewActiveViewer(self):
      patterns.Publisher().registerObserver(self.onEvent,
          eventType=self.container.viewerChangeEventType())
      self.container.onPageChanged(DummyEvent(1))
      self.failUnless(self.events)

  def testCloseViewer_RemovesViewerFromContainer(self):
      self.container.onPageClosed(DummyEvent())
      self.assertEqual([self.viewer2], self.container.viewers)

  def testCloseViewer_RemovesViewerFromSettings(self):
      self.container.onPageClosed(DummyEvent())
      self.assertEqual(1, self.settings.getint('view',
          'viewerwithdummywidgetcount'))

  def testCloseViewer_ChangesActiveViewer(self):
      self.container.onPageChanged(DummyEvent(1))
      self.container.onPageClosed(DummyEvent())
      self.assertEqual(self.viewer2, self.container.activeViewer())

Cheers, Frank

So I've been working on the whole duck typing and mock objects thing
with some success, but I would still love to be able to be able to
test a few "mouse-clicks." Because I thought it would be simple I
wrote the following test...

   def test__MainFrame__change_pages(self):
       mf = rollem.MainFrame(None)
       event =
wx.NotebookEvent(commandType=wx.wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED,
nSel=1)
       # event.SetSelection(1)
       mf.character_nb.ProcessEvent(event)
       assert mf.character_nb.GetCurrentPage().GetLabel() == 'Skills'

It always fails because the CurrentPage never changes from Page0. I
have tried explicitly setting the page involved with the commented-out
SetSelection() but that fails too.

I'm sure there's something simple that I am missing, but I am not sure
what it might be.

In most cases the sending of an event doesn't cause the thing to happen in
the native widget, it is just notifying the program that it did happen. So
to do what you intend with the code above you would actually have to
synthesize a native mouse press event, followed by a native mouse release
and then wait for the native widget to catch those events, process them and
then finally do the work to change the selected page. Unfortunately the
native event synthesis is not something that we can do yet from wx.

--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!

--
Stand Fast,
tjg. [Timothy Grant]