Mocking wxpython for unit testing
Unit testing GUI code is usually a pain, but Python makes this so easy that I laugh with glee every time I do it.
My approach is to declare my own fake versions of the main wxpython widgets, and then overwrite the wx namespace with my fake classes. This idea is basically borrowed from a post on dirt simple. What would be serious black-magic voodoo in a lot of languages is a simple two-liner in python:
import wx
wx.__dict__.update(locals())
OK, so maybe you're saying, hey, you're not actually testing your wxpython code! Here's the deal:
- I don't really want to unit test wxpython.
- I want to mock elements that require user input, like file/dir dialogs, etc. This approach lets me simulate user interaction with the fake classes.
- Creating a
wx.Appfor every test is going to significantly slow down the execution of our unit tests. If my unit tests take 5 seconds to run instead of 2, I'm simply going to run them less often.
I'll test the actual GUI functionality using function/acceptance tests.
So now in my unit tests, all I need to do is import fakewidgets before my GUI code module(s), and fakewidgets works its magic.
>>> frame = wx.Frame(None)
Traceback (most recent call last):
<…traceback ommitted…>
wx._core.PyNoAppError: The wx.App object must be created first!
>>> import fakewidgets # Will overwrite wx namespace
>>> frame = wx.Frame(None)
>>> frame
<fakewidgets.Frame instance at 0x00C7F710>
>>>
The linked zip file (fakewidgets.zip) has my fakewidgets module. It's still not complete, since I've simply been adding classes/methods as I needed them for my unit tests, but it should be straightforward enough to add in what else you need. If you do, please pass your additions back on!
Here's how you might use the module to unit test your GUI code. Below is a very simple/silly program that pops up a frame window.
simpleframe.py
"""
import wx
class SimpleFrame(wx.Frame):
def __init__(self, *args, **kwargs):
wx.Frame.__init__(self, *args, **kwargs)
class SimpleApp(wx.App):
def OnInit(self):
frame = SimpleFrame(parent=None, title="Simple Frame")
frame.Show()
return 1
def main():
app = SimpleApp(0)
app.MainLoop()
if __name__ == "__main__":
main()
Here's how you could unit test this (I'm assuming that you're using the excellent nose module for unit testing).
import simpleframe
def test_main():
simpleframe.main()
class TestSimpleFrame(object):
def setup(self):
self.frame = simpleframe.SimpleFrame(None, title="Simple")
def test_create(self):
pass
class TestSimpleApp(object):
def setup(self):
self.app = simpleframe.SimpleApp(0)
def test_create(self):
pass
def test_on_init(self):
retval = self.app.OnInit()
assert retval == 1, retval
Look ma, no wx.App! We can even call functions that call App.MainLoop() with impunity.

Thanks for this, it helped me to build upon the classes you defined and to easily test my GUI application’s functionality that was separate from the UI.
My changes can be seen here: http://bazaar.launchpad.net/~sproaty/whyteboard/development/annotate/head%3A/fakewidgets/core.py
and my unit tests at http://bazaar.launchpad.net/~sproaty/whyteboard/development/annotate/head%3A/unitests.py
@Steven
Awesome, thanks for putting up your modifications. I’ve also made considerable additions to my library, and was just thinking about putting them up (like on pypi). Do you mind if I incorporate your additions as well?
Yes, of course, feel free to add them. The URL I posted still contains the most up-to-date versions, I haven’t really tracked the changes properly unfortunately.
If you also take a look at http://bazaar.launchpad.net/~sproaty/whyteboard/development/files/head%3A/fakewidgets/ then I’ve mocked a class from inside the /lib module, so it should be easy to add others in a similar fashion.
Sorry for the late reply, I forgot I had commented here!
This looks like a good idea, but is it for linux only? When I import fakewidgets I get an import error because I don’t have wxaddons installed. The only reference I could find for installing it said to install it with apt-get.
@Craig
That’s an artifact from an older version of wxPython, when the sized_controls library was in the wxaddons module. You can just delete the reference to wxaddons in the fakewidgets module. I have an updated fakewidgets, with lots more wxPython classes handled, which I’m planning on releasing to pypi pretty soon.
Hi Ryan,
When you add your fakewidgets to some site, canyou send me a link please? Many thanks.
@Steven
OK, I’ve created a simple home page for the new fakewidgets module here:
http://ginstrom.com/code/fakewidgets.html
I’ll put it up on pypi later.
Unit testing is the well known and famous approach to test the code. it can be used along with integration testing as well as regression testing to get more good results of testing. Try unit testing tools for making your testing tasks easy as we know that unit testing code is written at the same time when the whole application codes is developed by the developers.