Thursday, May 25, 2006

Functional/Acceptance Testing Using guitest

Introdution


guitest (http://gintas.pov.lt/guitest) by Gintautas Miliauskas is a helper
library for unit-testing GUI applications written in Python. In this article I
will demonstrate how to test a PyGTK application. This article assume you are
familiar with ``unittest`` module and unit testing.


Installation


The latest version 0.3.1 released on 2005-11-26 is available from here:
http://gintas.pov.lt/guitest/guitest-0.3.1.tar.gz . Invoke `python setup.py
install` to install the library into the local python's site-packages
directory. Alternatively you may simply copy the guitest subdirectory to your
project's main source directory.


Getting Started


Consider this example ::

import gtk

class HelloWorld(object):

def __init__(self):
self.window = gtk.Window()
self.button = gtk.Button("Hello")
self.window.add(self.button)
self.window.show_all()

def main(self):
gtk.main()

if __name__ == '__main__':
helloworld = HelloWorld()
helloworld.main()

Now think what are the things you have to test. Let's say you want to make
sure that button is a child of window. And you want to test the label of
button is "Hello".

Just look in to this code, should be very easy to understand. ::

import unittest
import gtk
from guitest.gtktest import GtkTestCase

import hello1


class TestHelloWorld(GtkTestCase):

def test_simple_run(self):
helloworld = hello1.HelloWorld()

def test_button(self):
helloworld = hello1.HelloWorld()
button = helloworld.window.get_child()
assert type(button) == gtk.Button

def test_button_text(self):
helloworld = hello1.HelloWorld()
button = helloworld.window.get_child()
assert button.get_label() == "Hello"


def test_suite():
suite = unittest.TestSuite()
suite.addTest(unittest.makeSuite(TestHelloWorld))
return suite


if __name__ == '__main__':
unittest.main()

The test case class is inheriting from ``GtkTestCase``. `test_simple_run` is
just running the app. Other two test cases are self explanatory, yes! you
should be familiar with gtk api, that's all.

When testing gui, dialog handlers will be very usefull. We will extend the
first example::

import gtk

class HelloWorld(object):

def __init__(self):
self.window = gtk.Window()
self.button = gtk.Button("Hello")
self.button.connect("clicked", self.on_button_clicked)
self.window.add(self.button)
self.window.show_all()

def on_button_clicked(self, *args):
dlg = gtk.MessageDialog(None, 0, gtk.MESSAGE_INFO, gtk.BUTTONS_OK)
dlg.set_markup("OK")
ret = dlg.run()
dlg.destroy()
return ret

def main(self):
gtk.main()

if __name__ == '__main__':
helloworld = HelloWorld()
helloworld.main()

Here is setting a dialog handler for 'Hello' button and testing the label text::

import unittest
import gtk
from guitest.gtktest import GtkTestCase, guistate

import hello2

class TestHelloWorld(GtkTestCase):

def test_button_clicked(self):
helloworld = hello2.HelloWorld()
button = helloworld.button
guistate.dlg_handler = self.handle_hello_clicked
button.emit("clicked")

def handle_hello_clicked(self, dlg, *args):
label = dlg.label
if label.get_label() == "OK":
return gtk.RESPONSE_OK
else:
self.fail("Label is not 'OK'")


def test_suite():
suite = unittest.TestSuite()
suite.addTest(unittest.makeSuite(TestHelloWorld))
return suite


if __name__ == '__main__':
unittest.main()

For experimenting this code, just change the assertion, 'label.get_label() ==
"OK"'. If there is another dialog box coming after 'OK' button clicked, you
can add a new handler inside `handle_hello_clicked` function. For example::

def handle_hello_clicked(self, dlg, *args):
label = dlg.label
if label.get_label() == "OK":
guistate.dlg_handler = self.handle_ok_clicked
return gtk.RESPONSE_OK
else:
self.fail("Label is not 'OK'")

Tuesday, May 23, 2006

What to write?!

For the last one month I didn't wrote anything here.
I have always wondered how some peoples write long
matters in journal/blog. Is it just like composing
reply to a technical mail. Do they feel the pain
of creativity. I usually read python, gnome and ubuntu
planets. I like new ideas in programming, technology
also I read humor and philosophy. I think most of the
planets didn't restrict topics. Some of them writes
highly technical stuff only, some writes about life
some writes what's happening everywhere else.
Well, it is something like this, a type is declared
"int me1;", "float me2;". Yes some people sometimes
upcast or downcast their values :)
And there are few dynamically typed journals/blogs
and I like those very much, the first example
I can point is Guido's blog
(http://www.artima.com/weblogs/index.jsp?blogger=guido).
So a "Pythonic blog is always dynamically typed" :)
What is your favorite dynamically typed blog/journal?