pythonpython-2.7unit-testingwxpythonassertraises

unittest: wxpython's event method raises exception but assertRaises does not detect it


I have a wxpython dialog which raises a TypeError exception when clicking the OK button. I would like to test the occurrence of the exception with unittest but the test does not work as expected. The output shows that the exception is raised. Anyhow unittest notifies that the test fails:

"C:\Program Files (x86)\Python\python.exe" test.py
Traceback (most recent call last):
  File "test.py", line 22, in on_ok
    raise TypeError( 'TypeError raised' )
TypeError: TypeError raised
F
======================================================================
FAIL: test_should_raise (__main__.CDlgTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "test.py", line 34, in test_should_raise
    self._dut.m_button_ok.GetEventHandler().ProcessEvent( event )
AssertionError: TypeError not raised

----------------------------------------------------------------------
Ran 1 test in 0.005s

FAILED (failures=1)

Here is a reduced sample of my code:

import unittest
import wx

class CDlgBase ( wx.Dialog ):
    """The UI"""
    def __init__( self, parent ):
        wx.Dialog.__init__ ( self, parent )
        bSizerTest = wx.BoxSizer( wx.VERTICAL )
        self.m_button_ok = wx.Button( self, wx.ID_ANY )
        bSizerTest.Add( self.m_button_ok, 0 )
        self.SetSizer( bSizerTest )
        # Connect Events
        self.m_button_ok.Bind( wx.EVT_BUTTON, self.on_ok )
    def on_ok( self, event ):
        event.Skip()

class CDlg( CDlgBase ) :
    """The dialog"""
    def __init__(self, parent):
        super( CDlg, self).__init__(parent)
    def on_ok(self, event):
        # The exception should be verified in the test `test_should_raise()`.
        raise TypeError( 'TypeError raised' )

class CDlgTest( unittest.TestCase ) :
    """The test class"""
    def setUp(self):
        self._dut = CDlg(None)
    def test_should_raise(self):
        """The test to verify raising the TypeError exception in the event 
        method `on_ok()`. this is the test method which works not as expected."""
        event = wx.CommandEvent( wx.EVT_BUTTON.evtType[0] )
        event.SetEventObject( self._dut.m_button_ok )
        with self.assertRaises( TypeError ) :
            """Simulate an "OK" click. `on_ok()` will be executed 
            and raises the TypeError exception."""
            self._dut.m_button_ok.GetEventHandler().ProcessEvent( event )

if __name__ == '__main__':
    app = wx.App()
    tests = [ unittest.TestLoader().loadTestsFromTestCase( CDlgTest) ]
    unittest.TextTestRunner(verbosity=2, failfast=True).run(unittest.TestSuite(tests) )

Can somebody please help me to find out what I did wrong?


Solution

  • See: https://wiki.wxpython.org/CppAndPythonSandwich

    Exceptions are not passed up the call stack though the C++ layers. When control returns to C++ from Python then it checks if there was a Python exception that was not caught, if so then it prints and then clears the error.

    One way to deal with this in unit tests is to catch the exception in your event handler, and set a flag. Then back in the test code you can check for that flag being set or not.